1 原型模式
指定创建对象的种类,并且通过拷贝这些原型,创建新的对象,是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。这种模式现了一个原型接口,该接口用于创建当前对象的克隆。
原型模式的构成:
- Prototype : 原型类,声明一个克隆自己的接口
- ConcretePrototype: 具体的原型类, 实现一个克隆自己的操作
- Client: 让一个原型对象克隆自己,从而创建一个新的对象(属性一样)
2 例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| 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() + '}'; } }
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 + '\'' + '}'; } }
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 ); }
}
|
3 浅拷贝和深拷贝
基本数据类型的成员变量:
- 浅拷贝:直接进行值传递,该属性值复制一份给新的对象。
- 深拷贝:直接进行值传递,该属性值复制一份给新的对象。
引用数据类型的成员变量:
- 浅拷贝:将该成员变量的引用值(内存地址)复制一份给新的对象。
- 深拷贝:创建一个新对象,赋值。
4 深拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| @Override protected Object clone() { Sheep sheep = null; try { sheep = (Sheep)super.clone(); sheep.setCountry((Country)this.country.clone()); } catch (Exception e){ System.out.println(e.getMessage()); } return sheep; }
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(); }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() + '}'; } }
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 ); } }
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 原则,这点请同学们注意.