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

优缺点
- 性能好
原型模式是内存二进制流侧拷贝,要比直接new一个对象性能好很多,特别在一个循环体内产生大量的对象时,原型模式可以更好的体现其优点。
- 逃避构造函数的约束
直接在内存中拷贝,构造函数不会执行。优点和缺点都是减少了约束。
使用场景
需要频繁的new一个对象,并且该对象需要繁琐的数据准备时;
一个对象要提供给其他对象访问,各个调用者可能需要修改其值时;
原型模式一般与工厂方法模式一起出现,通过clone的方法来创建对象,然后由工厂方法提供给调用者。
实现
1 2 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只是拷贝本对象,对于其内部的数组、引用对象都不拷贝还是指向原声对象的内部元素地址。
1 2 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方式实现:
1 2 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接口)写到一个流中,然后再从流里把对象读出来以实现深克隆。
1 2 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提高篇——对象克隆(复制)