设计模式之原型模式20
背景
当我们发送邮件的时候需要模板来设置一些固定的东东。用到Template。然而,我们在发送时,一个Mail对象被发送多次,为了提升速度需要用到多线程来处理,这时就会有对象数据不安全。这时用到了Cloneable接口来解决这个问题。
类图
代码实现
定义一个模板类
public class AdvTemplate {
private String subject = "中奖拉,中了500万";
private String content = "中奖拉,中了500万。先交3000块定金";
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
再定义一个邮件,聚合模板
public class Mail implements Cloneable{
private String subject;
private String content;
private String receiver;
private String tail;
private ArrayList<String> test = new ArrayList<String>();
public Mail(AdvTemplate _template) {
this.subject = _template.getSubject();
this.content = _template.getContent();
}
@SuppressWarnings("unchecked")
@Override
public Mail clone() {
Mail mail = null;
try {
//浅clone,浅clone时String类型的可以被clone,而对象类型属性则不可以
mail = (Mail) super.clone();
//深clone,可以clone对象属性
mail.test = (ArrayList<String>) this.test.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return mail;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
}
客户端调用
public class Client {
public static void main(String[] args) {
Mail src = new Mail(new AdvTemplate());
int count = 6;
for(int i=0; i<count; i++) {
//浅clone,解决多线程访问不安全的问题
Mail mail = src.clone();
mail.setReceiver(getRandomString(9));
mail.setTail(" to " + mail.getReceiver());
sendMail(mail);
}
}
public static void sendMail(Mail mail) {
System.out.println("send to " + mail.getReceiver() + "@qq.com\t" + mail.getSubject() + "\t" +
mail.getContent() + "\t" + mail.getTail());
}
public static String getRandomString(int number) {
//防止拼错26个字母
char[] msg = new char['z'-'a' + 1];
for(int i='a'; i<='z'; i++) {
msg[i - 'a'] = (char) i;
}
Random random = new Random();
StringBuffer result = new StringBuffer();
for(int i=0; i<number; i++) {
result.append(msg[random.nextInt(msg.length)]);
}
return result.toString();
}
}
运行结果
send to vdkknjljy@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to vdkknjljy
send to sjhbkropv@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to sjhbkropv
send to jprscjyzd@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to jprscjyzd
send to hstzbxxkn@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to hstzbxxkn
send to dskpvhjrg@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to dskpvhjrg
send to bhiwuwzep@qq.com 中奖拉,中了500万 中奖拉,中了500万。先交3000块定金 to bhiwuwzep