假设我们需要做一个邮件发送系统,发送给银行客户的人,具体类图如下:
具体代码实例如下:
Mail:
public class Mail {
private String receiver;
private String subject;
private String appellation;
private String context;
private String tail;
public Mail(AdvTemplate advTemplate){
this.subject = advTemplate.getAdvSubject();
this.context = advTemplate.getAdvContext();
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAppellation() {
return appellation;
}
public void setAppellation(String appellation) {
this.appellation = appellation;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
AdvTemplate:
public class AdvTemplate {
private String advSubject = "老许抽奖活动";
private String advContext = "抽奖就送100w";
public String getAdvContext() {
return advContext;
}
public String getAdvSubject() {
return advSubject;
}
}
测试类如下:
public class Client {
private static final int MAX_COUNT = 6;
public static void main(String[] args) {
int i = 0;
mail.setTail("老许版权所有...");
while ( i < MAX_COUNT ){
Mail mail = new Mail(new AdvTemplate());
mail.setReceiver(getRandomString(5)+"@"+getRandomString(8)+".com");
mail.setAppellation(getRandomString(5)+"先生(女士)");
i++;
sendEmail(mail);
}
}
public static void sendEmail(Mail mail){
System.out.println("标题"+mail.getSubject()+"\t收件人"+mail.getReceiver()+"\t发送成功...");
}
public static String getRandomString(int num){
String source ="abcdefghijklmnopqrskuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < num; i++) {
sb.append(source.charAt(random.nextInt(source.length())));
}
return sb.toString();
}
}
测试结果如下:
由于是随机数,每次运行都有所差异,不管怎么样,我们这个发送程序是编写出来了,也能正常发送。我们再来仔细地想想,这个程序是否有问题?Look here,这是一个线程在运行,也就是你发送的是单线程的,那按照一封邮件发出去需要0.02秒(够小了,你还要到数据库中取数据呢),600万封邮件需要33个小时,也就是一个整天都发送不完,今天的没发送完,明天的账单又产生了,日积月累,激起甲方人员一堆抱怨,那怎么办?
好办,把sendMail修改为多线程,但是只把sendMail修改为多线程还是有问题的呀,产生第一封邮件对象,放到线程1中运行,还没有发送出去;线程2也启动了,直接就把邮件对 象mail的收件人地址和称谓修改掉了,线程不安全了。说到这里,你会说这有N多种解决办 法,其中一种是使用一种新型模式来解决这个问题:通过对象的复制功能来解决这个问题, 类图稍做修改:
我们来看修改后的邮件类:
public class Mail implements Cloneable{
private String receiver;
private String subject;
private String appellation;
private String context;
private String tail;
public Mail(AdvTemplate advTemplate){
this.subject = advTemplate.getAdvSubject();
this.context = advTemplate.getAdvContext();
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAppellation() {
return appellation;
}
public void setAppellation(String appellation) {
this.appellation = appellation;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
@Override
protected Mail clone() {
Mail mail = null;
try {
mail = (Mail)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return mail;
}
}
修改后的场景类:
public static void main(String[] args) {
Mail mail = new Mail(new AdvTemplate());
int i = 0;
mail.setTail("老许版权所有...");
while ( i < MAX_COUNT ){
Mail clone = mail.clone();
clone.setReceiver(getRandomString(5)+"@"+getRandomString(8)+".com");
clone.setAppellation(getRandomString(5)+"先生(女士)");
i++;
sendEmail(mail);
}
}
把对象复制一份,产生一个新的对象,和原有对象一样,然后再修改细节的数据,如设置称谓、设置收件人地址等。这种不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。
原型模式定义:
原型模式(Prototype Pattern)的简单程度仅次于单例模式和迭代器模式。正是由于简单,使用的场景才非常地多,其定义如下:
Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)
原型模式通用源码:
public class PrototypeClass implements Cloneable{
//覆写父类Object方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass)super.clone();
} catch (CloneNotSupportedException e) {
return prototypeClass;
}