我是靠谱客的博主 标致凉面,最近开发中收集的这篇文章主要介绍设计模式原则13----原型模式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

个人博客:打开链接

个性化电子账单

电子账单系统一般包括:账单分析、账单生成器、广告信管理、发送队列管理、发送机、退信处理、报表管理等功能。那既然是广告信,肯定需要一个模板,然后从数据库中把客户的信息一个一个地取出来,放到模板中生成一份完整的邮件,然后扔给发送机进行发送处理,类图为:
这里写图片描述
广告信模板代码:

public class AdvTemplate {
//广告信名称
private String advSubject = "XXX银行国庆信用卡抽奖活动";
//广告信内容
private String advContext = "国庆抽奖活动通知:只要刷卡就送你 一百万!...";
//获得广告信的名称
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 context;
//邮件的尾部,一般都是加上"XXX版权所有"等信息
private String tail;
//构造函数
public Mail(AdvTemplate advTemplate){
this.context = advTemplate.getAdvContext();
this.subject = advTemplate.getAdvSubject();
}
//以下为getter和setter方法
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;
}
}

场景类:


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("XXX银行版权所有");
while(i < MAX_COUNT){
//以下是每封邮件不同的地方
mail.setAppellation(getRandString(5) + " 先生(女士)");
mail.setReceiver(getRandString(5) + "@" + getRandString(8) + ".com");
//然后发送邮件
sendMail(mail);
i++;
}
}
//发送邮件
public static void sendMail(Mail mail){
System.out.println("标题:" + mail.getSubject() + "t收件人:"
+ mail.getReceiver() + "t...发送成功!");
}
//获得指定长度的随机字符串
public static String getRandString(int maxLength){
String source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuffer sb = new StringBuffer();
Random rand = new Random();
for(int i = 0; i < maxLength; i++){
sb.append(source.charAt(rand.nextInt(source.length())));
}
return sb.toString();
}
}

这是一个线程在运行,也就是你发送邮件是单线程的,假如发送一封邮件用时0.02秒,这已经够小了吧,那600万封邮件需要33个小时,这用时太长了,使我们无法接受的。所以,我们把sendMail改为多线程,来看一下修改过后的类图:
这里写图片描述
增加了一个Cloneable接口,Java自带的一个接口,Mail实现了这个接口,在Mail类中覆写clone()方法,代码清单如下:


public class Mail implements Cloneable{
//收件人
private String receiver;
//邮件名称
private String subject;
//称谓
private String appellation;
//邮件内容
private String context;
//邮件的尾部,一般都是加上"XXX版权所有"等信息
private String tail;
//构造函数
public Mail(AdvTemplate advTemplate){
this.context = advTemplate.getAdvContext();
this.subject = advTemplate.getAdvSubject();
}
@Override
public Mail clone(){
Mail mail = null;
try {
mail = (Mail)super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return mail;
}
//以下为getter和setter方法
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;
}
}

修改后的场景类:


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("XXX银行版权所有");
while(i < MAX_COUNT){
//以下是每封邮件不同的地方
Mail cloneMail = mail.clone();
cloneMail.setAppellation(getRandString(5) + " 先生(女士)");
cloneMail.setReceiver(getRandString(5) + "@" + getRandString(8) + ".com");
//然后发送邮件
sendMail(cloneMail);
i++;
}
}
//发送邮件
public static void sendMail(Mail mail){
System.out.println("标题:" + mail.getSubject() + "t收件人:"
+ mail.getReceiver() + "t...发送成功!");
}
//获得指定长度的随机字符串
public static String getRandString(int maxLength){
String source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuffer sb = new StringBuffer();
Random rand = new Random();
for(int i = 0; i < maxLength; i++){
sb.append(source.charAt(rand.nextInt(source.length())));
}
return sb.toString();
}
}

这种不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。

原型模式的定义

原型模式(Prototype Pattern): 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,Java提供了一个Cloneable接口来标识这个对象是可拷贝的。
原型模式的通用代码:

public class PrototypeClass implements Cloneable{
//覆写父类Object方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass) super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototypeClass;
}
}

实现一个接口,然后重写clone()方法,就完成了原型模式。

原型模式的优点

1、性能优良
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现优点
2、逃避构造函数的约束。
它不再需要构造函数,这既是它的优点,也是它的缺点

使用场景

1、资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等
2、性能和安全要求
通过new一个对象要非常繁琐的数据准备或访问权限,则可以使用原型模式
3、一个对象提供给多个修改者
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑原型模式拷贝多个对象供调用者使用。

注意事项

  • 当clone一个对象时,构造函数不会被执行。Object类的clone()方法的原理是从内存中(具体来说就是堆内存)以二进制流的方式进行拷贝,从新分配一个内存块,那构造函数没有被执行也是非常正常的了。
  • Object类提供的方法clone只是拷贝对象,其内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝叫做浅拷贝。
  • 让ArrayList成为深拷贝:this.arrayList = (ArrayList)this.arrayList.clone();
  • 要是有clone()方法,类的成员变量上不要增加final关键字。

最后

以上就是标致凉面为你收集整理的设计模式原则13----原型模式的全部内容,希望文章能够帮你解决设计模式原则13----原型模式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部