原型模式
不通过new关键字来产生一个对象,而通过对象复制来生产对象的模式,原型模式的核心是clone方法,通过该方法进行对象的拷贝。
也就是先生产出一个包含大量共有信息的类对象,然后拷贝出副本修正细节信息,建立一个完整的个性对象。
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

优缺点
- 性能好
 原型模式是内存二进制流侧拷贝,要比直接new一个对象性能好很多,特别在一个循环体内产生大量的对象时,原型模式可以更好的体现其优点。
- 逃避构造函数的约束
 直接在内存中拷贝,构造函数不会执行。优点和缺点都是减少了约束。
使用场景
需要频繁的new一个对象,并且该对象需要繁琐的数据准备时;
一个对象要提供给其他对象访问,各个调用者可能需要修改其值时;
原型模式一般与工厂方法模式一起出现,通过clone的方法来创建对象,然后由工厂方法提供给调用者。
实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | public class PrototypeClass implements Cloneable{@Override
 public PrototypeClass clone(){
 PrototypeClass p = null;
 try{
 p = (PrototypeClass)super.clone();
 }catch(CloneNotSupportedException e){
 
 }
 return p;
 }
 }
 
 | 
注意事项
构造函数不会被执行
Object类的clone方法原理是从内存中(堆内存)以二进制流的方式进行拷贝,重新分配一个内存快,构造函数是不会被执行的。
浅拷贝
Object类提供的方法clone只是拷贝本对象,对于其内部的数组、引用对象都不拷贝还是指向原声对象的内部元素地址。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public class PrototypeClass implements Cloneable{public ArrayList<String> arrayList = new ArrayList<>();
 
 @Override
 public PrototypeClass clone(){
 PrototypeClass p = null;
 try{
 p = (PrototypeClass) super.clone();
 }catch(CloneNotSupportedException e) ) {
 
 }
 return p;
 }
 }
 
 | 
深拷贝
深拷贝需要拷贝对象自身外,还需要拷贝对象的所有引用的对象。
通过clone方式实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | public class PrototypeClass implements Cloneable{public ArrayList<String> arrayList = new ArrayList<>();
 
 @Override
 public PrototypeClass clone(){
 PrototypeClass p = null;
 try{
 p = (PrototypeClass) super.clone();
 p.arrayList = (ArrayList<String>) this.arrayList.clone();
 }catch(CloneNotSupportedException e) ) {
 
 }
 return p;
 }
 }
 
 | 
通过序列化方式来实现,通过序列化将对象(该对象的类必须实现Serializable接口)写到一个流中,然后再从流里把对象读出来以实现深克隆。
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | public static <T extends Serializable> T clone(T t) throws Exception {ByteArrayOutputStream baos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(baos);
 oos.writeObject(t);
 
 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
 ObjectInputStream ois = new ObjectInputStream(bais);
 return (T)ois.readObject();
 }
 
 | 
clone与final的冲突
当使用clone方法的时候,类的成员变量不可以增加final关键字。
拓展:
Java提高篇——对象克隆(复制)