原型模式

来源:互联网 发布:db2查看数据库列表 编辑:程序博客网 时间:2024/06/05 15:18

原型模式

原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后通过用复制这个原型对象的方法来创建出更多同类型的对象 –《JAVA与模式》

  • 原型模式优点

    作为原型模式来说,在Java中的实现基本上是通过Object中的clone实现的,之所以使用clone来实现,这样的做的好处有:在创建复杂的对象的时候,或者需要大量创建某同一对象时,调用目标类的构造方法效率低,而使用clone来实现对象创建,在一定程度上是提高了效率。

  • 原型模式两种表现形式

    • 简单形式
    public class SimplePrototype implements Cloneable {    @Override    protected SimplePrototype clone() throws CloneNotSupportedException {        return (SimplePrototype) super.clone();    }    public void doSomething() {        System.out.println("我已经被clone了");    }}public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        SimplePrototype simplePrototype = new SimplePrototype();        for (int i = 0; i < 100; i++) {            SimplePrototype tempSimplePrototype = simplePrototype.clone();            tempSimplePrototype.doSomething();        }    }}
    • 登记形式

    相对于简单形式的而言,登记形式只是多了一个原型管理器角色,而这个角色的主要作用是:创建具体原型类的对象,并记录每一个被创建的对象。

    public class RegisterPrototype implements Cloneable {    private String name;    @Override    protected RegisterPrototype clone() throws CloneNotSupportedException {        return (RegisterPrototype) super.clone();    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}public class RegisterPrototypeManager {    /**     * 注册表     */    private static final Map<String, RegisterPrototype> register = new ConcurrentHashMap<String, RegisterPrototype>();    private RegisterPrototypeManager() {    }    /**     * 注册原型     * @param registerPrototype     */    public static void register (RegisterPrototype registerPrototype) {        register.put(registerPrototype.getName(), registerPrototype);    }    /**     * 注销原型     * @param name     * @return     */    public static RegisterPrototype remove(String name) {        return register.remove(name);    }    /**     * 获取原型     * @param name     * @return     */    public static RegisterPrototype getPrototype(String name) {        RegisterPrototype registerPrototype = register.get(name);        if (registerPrototype == null) {            throw new RuntimeException("没有注册该类型的原型,或该类型的原型已被注销");        }        return registerPrototype;    }}public class RegisterClient {    public static void main(String[] args) throws CloneNotSupportedException {        RegisterPrototype registerPrototype = new RegisterPrototype();        // 向注册容器中注册10个clone对象        for (int i = 0; i < 10; i++) {            RegisterPrototype tempRegisterPrototype = registerPrototype.clone();            tempRegisterPrototype.setName(String.valueOf(i));            RegisterPrototypeManager.register(tempRegisterPrototype);        }        for (int i = 0; i < 10; i++) {            RegisterPrototype tempRegisterPrototype = RegisterPrototypeManager.getPrototype(String.valueOf(i));            System.out.println(tempRegisterPrototype);        }    }}
  • 两种形式比较

    两种原型形式有各自的优势,当原型比较少,类型比较单一,简单那么可以使用简单形式的原型模式;但是假如说原型的数量不确定,那么则需要使用登记形式来同一管理所有原型。


Java中的深浅克隆

  • Java中的对象克隆实现

    Java中作为所有类的父类Object,他有一个方法clone方法,每一个Java都继承了这个方法,作为所有Object子类来说这个方法都是可见的,且可以去重写;但是有一点必须注意:任何需要被克隆的对象都必须实现Cloneable接口,才能被JVM安全的调起clone的方法

    在Java中实现克隆有三个条件需要遵守

    1. 对于任何对象而言,都应该是源对象和克隆对象不是一个对象
    2. 对于任何对象而言,都应该是源对象和克隆对象类型是一致的
    3. 对于任何对象而言,都应该是源对象和克隆对象相等(equals方法执行之后返回true)——关于这一点其实Java没有规定必须遵守,这是一个可选条件
  • Java中的浅克隆和深克隆

    • 浅克隆

    在克隆时只负责对象中的值传递,这其中包括了基本类型数据(或者其包装类型)以及String类型,可以理解为在浅克隆源对象时,这个源对象的中的引用类型是不会单独克隆一份出来,只是单纯的将JVM中的地址值传递给克隆对象,简单来说就是浅克隆之后,源对象和克隆对象中的引用类型指向的堆内存中的引用对象其实是同一个。

    浅克隆代码实现

    public class ShadowClone implements Cloneable {    public static class TempObject {        public TempObject () {}    }    private TempObject tempObject;    public ShadowClone(TempObject tempObject) {        super();        this.tempObject = tempObject;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public String toString() {        return "本身类的地址值:" + super.toString() + "|" + "引用类的地址值:" + tempObject;    }}public class TestShadowClone {    public static void main(String[] args) throws CloneNotSupportedException {        ShadowClone shadowCloneSource = new ShadowClone(new TempObject());        System.out.println("源对象:" + shadowCloneSource);        ShadowClone shadowCloneTarget = (ShadowClone) shadowCloneSource.clone();        System.out.println("目标对象:" + shadowCloneTarget);    }}
    • 深克隆

    相比较于浅克隆,深克隆,就是不仅克隆源对象本身,其中包括源对象中的基本类型和String类型,以及引用类型,当然这里存在一个值得注意的问题:就是我们的深克隆深度的决定,所谓的深度就是比如A对象中的成员变量B(引用类型),B对象中的成员变量C(引用类型),那么这里需要考虑的问题就是克隆的深度,简单来说就是克隆A对象也把B克隆了,也把B对象中的C克隆了,这样就达到了最大深度了;最后这里需要注意一点就是对象之间的引用出现了循环引用

    深克隆代码实现

    public class Body implements Cloneable, Serializable{    private int body;    public Body(int body) {        super();        this.body = body;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + body;        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Body other = (Body) obj;        if (body != other.body)            return false;        return true;    }}public class Foot implements Cloneable, Serializable{    private int foot;    public Foot(int foot) {        super();        this.foot = foot;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + foot;        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Foot other = (Foot) obj;        if (foot != other.foot)            return false;        return true;    }}public class Hand implements Cloneable, Serializable{    private int hand;    public Hand(int hand) {        super();        this.hand = hand;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + hand;        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Hand other = (Hand) obj;        if (hand != other.hand)            return false;        return true;    }}public class Head implements Cloneable, Serializable{    private int head;    public Head(int head) {        super();        this.head = head;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + head;        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Head other = (Head) obj;        if (head != other.head)            return false;        return true;    }}public class Human implements Cloneable, Serializable{    private Head head;    private Body body;    private Hand hand;    private Foot foot;    public Human(Head head, Body body, Hand hand, Foot foot) {        super();        this.head = head;        this.body = body;        this.hand = hand;        this.foot = foot;    }    @Override    protected Object clone() throws CloneNotSupportedException {        Human human = (Human) super.clone();        human.setBody((Body)human.getBody().clone());        human.setFoot((Foot)human.getFoot().clone());        human.setHand((Hand)human.getHand().clone());        human.setHead((Head)human.getHead().clone());        return human;    }    @Override    public String toString() {        Class clazz = this.getClass();        Field[] fields = clazz.getDeclaredFields();        StringBuilder stringBuilder = new StringBuilder();        stringBuilder.append(super.toString());        for (Field tempField : fields) {            tempField.setAccessible(true);            try {                stringBuilder.append(tempField.getName());                stringBuilder.append(":").append(tempField.get(this)).append("|");            } catch (IllegalArgumentException e) {                e.printStackTrace();            } catch (IllegalAccessException e) {                e.printStackTrace();            }        }        return stringBuilder.toString();    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((body == null) ? 0 : body.hashCode());        result = prime * result + ((foot == null) ? 0 : foot.hashCode());        result = prime * result + ((hand == null) ? 0 : hand.hashCode());        result = prime * result + ((head == null) ? 0 : head.hashCode());        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Human other = (Human) obj;        if (body == null) {            if (other.body != null)                return false;        } else if (!body.equals(other.body))            return false;        if (foot == null) {            if (other.foot != null)                return false;        } else if (!foot.equals(other.foot))            return false;        if (hand == null) {            if (other.hand != null)                return false;        } else if (!hand.equals(other.hand))            return false;        if (head == null) {            if (other.head != null)                return false;        } else if (!head.equals(other.head))            return false;        return true;    }    public Head getHead() {        return head;    }    public void setHead(Head head) {        this.head = head;    }    public Body getBody() {        return body;    }    public void setBody(Body body) {        this.body = body;    }    public Hand getHand() {        return hand;    }    public void setHand(Hand hand) {        this.hand = hand;    }    public Foot getFoot() {        return foot;    }    public void setFoot(Foot foot) {        this.foot = foot;    }}public class TestCloneMethod {    public static void main(String[] args) throws CloneNotSupportedException {        Human human = new Human(new Head(1), new Body(1), new Hand(1), new Foot(1));        System.out.println("这是原型" + human);        Human humanClone = (Human) human.clone();        System.out.println("这是克隆" + humanClone);        System.out.println("两个对象是否相等:" + human.equals(humanClone));    }}
    • 使用Stream进行深克隆
    public class TestStreamClone {    public static void main(String[] args) throws IOException, ClassNotFoundException {        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);        Human human = new Human(new Head(1), new Body(1), new Hand(1), new Foot(1));        System.out.println("原型是:" + human.toString());        objectOutputStream.writeObject(human);        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);        Human humanClone = (Human) objectInputStream.readObject();        System.out.println("克隆是:" + humanClone.toString());        System.out.println("两个对象是否相等:" + human.equals(humanClone));    }}

    上述博客部分内容参考《JAVA与模式》之原型模式

0 0
原创粉丝点击