设计模式-原型模式
用原型实例指定创建对象的种类,通过拷贝这些原型创建新的对象。
电子账单
即,使用电子账单
// 广告信模板
public class AdvTemplate {
// 广告信名称
private String advSubject = "XX活动";
// 广告内容
private String advContext = "XX活动";
// 取得广告名称
public String getAdvSubject(){
return this.advSubject;
}
// 取得广告信内容
public String getAdvContext(){
return this.advContext;
}
}
// 邮件
public class Mail {
// 收件人
private String receiver;
// 邮件名称
private String subject;
// 称谓
private String appellation;
// 邮件内容
private String contxt;
// 邮件尾部
private String tail;
// 构造函数
public Mail(AdvTemplate advTemplate){
this.contxt = advTemplate.getAdvContext();
this.subject = advTemplat.getAdvSubject()
}
// get set方法
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 getApplation(){
return applation;
}
public void setApplation(String applation){
this.appellation = applation
}
public String getContxt(){
return contxt;
}
public void setContxt(String contxt){
this.contxt = contxt;
}
public String getTail(){
return tail;
}
public void setTail(String tail){
this.tail = tail;
}
}
最后绘制场景
public class Client {
// 发送账单的数量
private static int MAX_COUNT = 6;
public static void main(String[] args){
// 模拟发送邮件
int i = 0;
// 模板定义
Mail mail = new Mail(new AdvTemplate());
mail.setTail(" ");
while(i < MAX_COUNT){
mail.setAppllation(getRandString(5) + "先生(女士)");
mail.setReceiver(getRandString(5) + "@" + mail.getRandString() + ".com");
// 发送邮件
sendMail(mail);
i++;
}
}
// 发送邮件
public static void sendMail(Mail mail){
System.out.println("标题" + mail.getSubject() + "发送成功");
}
// 获取指定长度的随机字符串
public static String getRandString(int maxLength){
String source = "abcdefghijklmnopqrstuvwxyz";
// 缓冲区
StringBuffer sb = new StringBuffer();
// 随机数
Random rand = new Random();
// 进行循环
for(int i = 0; i < maxLength; i++){
// 进行随机取字符数
sb.append(source.charAt(rand.nextlnt(source.length()))); // rand.nextInt() 生成伪随机数,放入到缓冲区内
}
return sb.toString(); // 返回生成的伪字符串
}
}
使用多线程改进
由于是一个线程发送邮件过慢,使用多线程解决问题。
增加一个Cloneable接口
关于克隆
克隆用途
关于Cloneable 接口,用途和Serializable一样为标记型接口,内部没有方法和属性,implements Cloneable 表示对象能被克隆,即能使用Object.clone()方法,
关于深浅拷贝
这个已经重复多次了。。。。。。。。。再js里已经重复了一次
浅拷贝,只单单拷贝本身,不拷贝引用。
深拷贝,完整的递归拷贝。
修改后的代码
public class Mail implements Cloneable { // 继承自java本身就有的空接口,即Cloneable
// 收件人
private String receiver;
// 邮件名称
private String subject;
// 称谓
private String appellation;
// 邮件内容
private String contxt;
// 邮件尾部
private String tail;
// 构造函数
public Mail(AdvTemplate advTemplate){
this.contxt = advTemplate.getAdvContext();
this.subject = advTemplat.getAdvSubject()
}
// 下面进行浅拷贝,重写clone方法
@Override
public Mail clone(){
Mail mail = null;
try{
mail = (Mail)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return mail;
}
// get set方法
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 getApplation(){
return applation;
}
public void setApplation(String applation){
this.appellation = applation
}
public String getContxt(){
return contxt;
}
public void setContxt(String contxt){
this.contxt = contxt;
}
public String getTail(){
return tail;
}
public void setTail(String tail){
this.tail = tail;
}
}
然后修改场景类
public class Client {
// 发送账单的数量
private static int MAX_COUNT = 6;
public static void main(String[] args){
// 模拟发送邮件
int i = 0;
// 模板定义
Mail mail = new Mail(new AdvTemplate());
mail.setTail(" ");
while(i < MAX_COUNT){
Mail cloneMail = mail.clone();
cloneMail.setAppllation(getRandString(5) + "先生(女士)");
cloneMail.setReceiver(getRandString(5) + "@" + mail.getRandString() + ".com");
// 发送邮件
sendMail(cloneMail );
i++;
}
}
// 发送邮件
public static void sendMail(Mail mail){
System.out.println("标题" + mail.getSubject() + "发送成功");
}
// 获取指定长度的随机字符串
public static String getRandString(int maxLength){
String source = "abcdefghijklmnopqrstuvwxyz";
// 缓冲区
StringBuffer sb = new StringBuffer();
// 随机数
Random rand = new Random();
// 进行循环
for(int i = 0; i < maxLength; i++){
// 进行随机取字符数
sb.append(source.charAt(rand.nextlnt(source.length()))); // rand.nextInt() 生成伪随机数,放入到缓冲区内
}
return sb.toString(); // 返回生成的伪字符串
}
}
使用拷贝,将sendMail放入线程池里,每次拷贝一个对象,然后将对象放入sendMail,然后将sendMail放入线程里,每次运行一个线程,拷贝一个对象,这样解决,一个线程还未发送完成邮件的时候,就传入的对象被修改的问题。
最后 深拷贝
实现深拷贝
在clone内部,将该对象引用的对象,再次进行拷贝即可。
应用
打飞机游戏中,主飞机,使用单例模式,其余飞机,使用原型模式,以一架飞机为原型,生成多个飞机。后者使用深拷贝。