4 原型模式
定义:通过复制现有实例来创建新的实例,无需知道相应类的信息。
简单地理解,其实就是当需要创建一个指定的对象时,我们刚好有一个这样的对象,但是又不能直接使用,我会clone一个一毛一样的新对象来使用;基本上这就是原型模式。关键字:Clone。
4.1 深拷贝和浅拷贝
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。clone明显是深复制,clone出来的对象是是不能去影响原型对象的
4.2 原型模式的结构和代码示例
Client:使用者
Prototype:接口(抽象类),声明具备clone能力,例如java中得Cloneable接口
ConcretePrototype:具体的原型类
可以看出设计模式还是比较简单的,重点在于Prototype接口和Prototype接口的实现类ConcretePrototype。原型模式的具体实现:一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB,因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法。
public class Prototype implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
}
举例(银行发送大量邮件,使用clone和不使用clone的时间对比):我们模拟创建一个对象需要耗费比较长的时间,因此,在构造函数中我们让当前线程sleep一会
public Mail(EventTemplate et) {
this.tail = et.geteventContent();
this.subject = et.geteventSubject();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
不使用clone,发送十个邮件
public static void main(String[] args) {
int i = 0;
int MAX_COUNT = 10;
EventTemplate et = new EventTemplate("9月份信用卡账单", "国庆抽奖活动...");
long start = System.currentTimeMillis();
while (i < MAX_COUNT) {
// 以下是每封邮件不同的地方
Mail mail = new Mail(et);
mail.setContent(getRandString(5) + ",先生(女士):你的信用卡账单..." + mail.getTail());
mail.setReceiver(getRandString(5) + "@" + getRandString(8) + ".com");
// 然后发送邮件
sendMail(mail);
i++;
}
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
用时:10001
使用clone,发送十个邮件
public static void main(String[] args) {
int i = 0;
int MAX_COUNT = 10;
EventTemplate et = new EventTemplate("9月份信用卡账单", "国庆抽奖活动...");
long start=System.currentTimeMillis();
Mail mail = new Mail(et);
while (i < MAX_COUNT) {
Mail cloneMail = mail.clone();
mail.setContent(getRandString(5) + ",先生(女士):你的信用卡账单..."
+ mail.getTail());
mail.setReceiver(getRandString(5) + "@" + getRandString(8) + ".com");
sendMail(cloneMail);
i++;
}
long end=System.currentTimeMillis();
System.out.println("用时:"+(end-start));
}
用时:1001
4.3 总结
原型模式的本质就是clone,可以解决构建复杂对象的资源消耗问题,能再某些场景中提升构建对象的效率;还有一个重要的用途就是保护性拷贝,可以通过返回一个拷贝对象的形式,实现只读的限制。