我是靠谱客的博主 标致凉面,这篇文章主要介绍设计模式原则13----原型模式,现在分享给大家,希望可以做个参考。

个人博客:打开链接

个性化电子账单

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AdvTemplate { //广告信名称 private String advSubject = "XXX银行国庆信用卡抽奖活动"; //广告信内容 private String advContext = "国庆抽奖活动通知:只要刷卡就送你 一百万!..."; //获得广告信的名称 public String getAdvSubject() { return this.advSubject; } //获得广告信的内容 public String getAdvContext() { return this.advContext; } }

邮件类代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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; } }

场景类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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()方法,代码清单如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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; } }

修改后的场景类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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接口来标识这个对象是可拷贝的。
原型模式的通用代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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----原型模式内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部