原型模式
定义:通过复制现有实例来创建新的实例,无需知道相应类的信息。
简单地理解,其实就是当需要创建一个指定的对象时,我们刚好有一个这样的对象,但是又不能直接使用,我会clone一个一毛一样的新对象来使用;基本上这就是原型模式。关键字:Clone。
1.1 深拷贝和浅拷贝
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。clone明显是深复制,clone出来的对象是是不能去影响原型对象的
1.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
1.3 总结
原型模式的本质就是clone,可以解决构建复杂对象的资源消耗问题,能再某些场景中提升构建对象的效率;还有一个重要的用途就是保护性拷贝,可以通过返回一个拷贝对象的形式,实现只读的限制。