引用《设计模式》第九章
0.《设计模式》摘录
- 问题:要构造一个图形编辑器框架,来构造各种图形编辑器。在设计这个框架时,不能预测到各种定制情况下可能有哪些Graphics子类。
- 解决:让每个图形元素有一个clone方法,Application通过调用图形元素对象的clone方法来创建这种类型的对象
而Application并不需要知道这个对象的具体类是什么。
而且可以随时增加图形元素的种类而不影响已有的种类的使用。
1.问题
在投简历的时候,给不同公司投的简历相同,在代码层面,有几种方式处理:
- ctlc+ctrlv,这样既不高效,而且臃肿,而且易出错
- 建立简历类,重复new Resume()来创建简历,但对每个简历都要做相同的设置,比如调用r.setName(“小明”),有很多重复的代码。
2.原型模式
2.1 定义
原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节
2.2 结构图和代码
-
抽象原型类
abstract class Prototype { private String id; public Prototype(String id)//构造器 { this.id=id; } public getId() { System.out.println(); } public abstract Prototype Clone();//不同的原型类有不同的克隆方式 }
-
具体原型类
class ConcretePrototype1 extends Prototype { public abstract Prototype Clone()//不同的原型类有不同的克隆方式 { return (Prototype)super.clone(); //浅表复制,对于对象型属性是复制其地址而不是引用的对象。 //所以原始对象和复制对象引用同一个对象 }; }
-
客户端
static void Mian(String[] args) { ConcretePrototype1 p1=new ConcreteProtetype("xiaoming"); ConcreteProtetype p2=(ConcretePrototype)p1.clone();//这样就实现了复制 }
2.4 浅复制和深复制
具体原型类ConcretePrototype1采用的是浅复制(见上文注释)
深表复制:现在Resume里面有个类WorkRxperience work,则Resume在重写clone()需要调用work的clone()。
-
work类
class WorkExperience { ... public Object Clone() { return (Object)super.clone(); } }
-
resume类
class Resume { private int age; private String name; private WorkExperience work;//有一个属性是对象 public Resume(String name)//外部调用时使用的构造器 { ... } private Resume(WorkExperience work)//注意⚠:这个构造器是private,只是会在自己的clone中使用 { this.work=(WorkExperience)work.Clone(); } ... public Object Clone()//此时Resume父类是Object,所以返回类型是Object { Resume obj=new Resume(this.work);//注意:调用私有构造器,这样就将对象属性work复制了。 obj.age=this.age;//然后复制其他值 obj.name=this.name; return obj; } }
2.3 优点
不用重新初始化对象,而是动态地获得对象运行时的状态。
如果之前重复实例类的方法,每NEW次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么会很低效。克隆既隐藏了对象创建的细节,又对性能是大大的提高。