内容抄自《设计模式》清华大学出版社,2011
模式动机:
在软件系统中,有些对象的创建过程较为复杂,而且有的时候需要频繁创建,原型模式可以通过复制的方法,减少创建对象花费的时间。
模式定义:
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
角色:
1.抽象原型类 (需定义有克隆接口) 一般用Object.class
2.具体原型类 需实现(Cloneable:浅克隆,深克隆:序列化)
浅克隆: 克隆对象的内部普通成员引用没有改变
深克隆: 全部改变
优点:1.当对象实例化复杂时,可以简化
2.可以保存状态
缺点:1.需要对类增加clone,违反开闭
2.实现深克隆代码复杂
适用环境:1.创建新对象成本大,或者新对象与原对象相似
2.系统要保存状态,且状态变化小,或者对象本身占用内存不大
扩展:原型管理器,类似工厂
clone不会调用构造函数,
clone和new的效率对比,省略执行<init>() 方法
栗子:
/** 原型模式
* @author Administrator
*
*/
class PrototypeModel {
static class Email implements Cloneable,Serializable,CacheObj{
private static final long serialVersionUID = 1L;
public Attachment attachment = new Attachment();
public Email() {
super();
System.out.println("con");
}
@Override
public Email clone(){
Email email = null;
try {
email = (Email) super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return email;
}
public Email deepClone() throws Exception{
ByteArrayOutputStream stream = new ByteArrayOutputStream(1024);
ObjectOutputStream obstream = new ObjectOutputStream(stream);
obstream.writeObject(this);
ByteArrayInputStream in = new ByteArrayInputStream(stream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(in);
return (Email) objectInputStream.readObject();
}
}
static class Attachment implements Serializable{
private static final long serialVersionUID = 1L;
}
static interface CacheObj extends Cloneable{
public CacheObj clone();
}
static class PrototypeManager{
public ConcurrentHashMap<String,CacheObj> cache = new ConcurrentHashMap<>(16);
public CacheObj get(String key){
CacheObj object = cache.computeIfAbsent(key,k->{
System.out.println("cc");
return new Email();
});
return object.clone();
}
}
public static void main(String[] args) throws Exception {
Email email = new Email();
Email clone = email.clone();
System.out.println(email==clone);
System.out.println(email.attachment==clone.attachment);
PrototypeManager manager = new PrototypeManager();
CacheObj obj1 = manager.get("aa");
CacheObj obj2 = manager.get("aa");
CacheObj obj3 = manager.get("aa");
System.out.println(obj1);
System.out.println(obj2);
System.out.println(obj3);
}
}