Skip to content

Latest commit

 

History

History
230 lines (184 loc) · 7.74 KB

006.创建者模式_原型模式.md

File metadata and controls

230 lines (184 loc) · 7.74 KB

1 原型模式

指定创建对象的种类,并且通过拷贝这些原型,创建新的对象,是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。这种模式现了一个原型接口,该接口用于创建当前对象的克隆。

原型模式的构成:

  • Prototype : 原型类,声明一个克隆自己的接口
  • ConcretePrototype: 具体的原型类, 实现一个克隆自己的操作
  • Client: 让一个原型对象克隆自己,从而创建一个新的对象(属性一样)

2 例子

//克隆羊
public class Sheep implements Cloneable{

    private String name;

    private int age;

    public Country country; //对象,  克隆是会如何处理,  默认是浅拷贝

    public Sheep(String name, int age,Country country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }

    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep)super.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return sheep;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", country=" + country +
                ", countryHashCode=" + country.hashCode() +
                '}';
    }
   //省略 getter/setter
}

public class Country implements Cloneable{
    private  String name;

    @Override
    protected Object clone() {
        Country country = null;
        try {
            country = (Country)super.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return country;
    }

    @Override
    public String toString() {
        return "Country{" +
                "name='" + name + '\'' +
                '}';
    }
    //省略 getter/setter
}


public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("多利羊", 3,new Country("美国"));
        Sheep sheep1 = (Sheep)sheep.clone();
        Sheep sheep2 = (Sheep)sheep.clone();
        Sheep sheep3 = (Sheep)sheep.clone();
        Sheep sheep4 = (Sheep)sheep.clone();
        System.out.println("sheep1 =" + sheep1 );
        System.out.println("sheep2 =" + sheep2 );
        System.out.println("sheep3 =" + sheep3 );
        System.out.println("sheep4 =" + sheep4 );
    }

}

//输出:
//sheep1 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=356573597}
//sheep2 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=356573597}
//sheep3 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=356573597}
//sheep4 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=356573597}

3 浅拷贝和深拷贝

基本数据类型的成员变量:

  • 浅拷贝:直接进行值传递,该属性值复制一份给新的对象。
  • 深拷贝:直接进行值传递,该属性值复制一份给新的对象。

引用数据类型的成员变量:

  • 浅拷贝:将该成员变量的引用值(内存地址)复制一份给新的对象。
  • 深拷贝:创建一个新对象,赋值。

4 深拷贝

//方法一:将 Sheep 的 clone 修改为如下
@Override
protected Object clone() {
    Sheep sheep = null;
    try {
       sheep = (Sheep)super.clone();
       //对象修改为可 clone
       sheep.setCountry((Country)this.country.clone());
     } catch (Exception e){
       System.out.println(e.getMessage());
     }
       return sheep;
}
//输出:
//sheep1 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=356573597}
//sheep2 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=1735600054}
//sheep3 =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=21685669}
// =Sheep{name='多利羊', age=3, country=Country{name='美国'}, countryHashCode=2133927002}

//方法二:使用序列化
public class DeepSheep implements Serializable, Cloneable{

    private String name;

    private int age;

    public Country country; //对象,  克隆是会如何处理,  默认是浅拷贝

    public DeepSheep(String name, int age, Country country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }

    @Override
    protected Object clone() {
        DeepSheep sheep = null;
        try {
            sheep = deepClone();
            //sheep = SerializationUtils.deepCopy(this);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return sheep;
    }

    public DeepSheep deepClone() throws IOException,ClassNotFoundException{
        //将对象写入流中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(this);
        //从流中取出
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        return (DeepSheep)objectInputStream.readObject();
    }


    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", country=" + country +
                ", countryHashCode=" + country.hashCode() +
                '}';
    }
    //省略 getter/setter
}

public class Client {
    public static void main(String[] args) {
        DeepSheep deepSheep = new DeepSheep("汤姆羊", 3,new Country("法国"));
        DeepSheep deepSheep1 = (DeepSheep)deepSheep.clone();
        DeepSheep deepSheep2 = (DeepSheep)deepSheep.clone();
        DeepSheep deepSheep3 = (DeepSheep)deepSheep.clone();
        DeepSheep deepSheep4 = (DeepSheep)deepSheep.clone();
        System.out.println("deepSheep1 =" + deepSheep1 );
        System.out.println("deepSheep2 =" + deepSheep2 );
        System.out.println("deepSheep3 =" + deepSheep3 );
        System.out.println("deepSheep4 =" + deepSheep4 );
    }
}
//deepSheep1 =Sheep{name='汤姆羊', age=3, country=Country{name='法国'}, countryHashCode=1531448569}
//deepSheep2 =Sheep{name='汤姆羊', age=3, country=Country{name='法国'}, countryHashCode=1867083167}
//deepSheep3 =Sheep{name='汤姆羊', age=3, country=Country{name='法国'}, countryHashCode=1915910607}
//deepSheep4 =Sheep{name='汤姆羊', age=3, country=Country{name='法国'}, countryHashCode=284720968}

//深拷贝工具类
public class SerializationUtils {
    public static <T> T deepCopy(T src) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        @SuppressWarnings("unchecked")
        T dest = (T) in.readObject();
        return dest;
    }
}

5 注意事项

  • 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率

  • 不用重新初始化对象,而是动态地获得对象运行时的状态

  • 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码

  • 在实现深克隆的时候可能需要比较复杂的代码

  • 缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了 ocp 原则,这点请同学们注意.