原型模式很多人对这个设计模式也是不熟悉的。因为用得也是不多,原型模式一般用于多次创建一个类的对象,获取多个这个类的对象,并进行相应的操作,一般做法是多次new出来,但是原型模式是复制第一次创建的对象,然后通过多次复制得到多个对象。这种需求可能在现实需求中比较少,但是了解多一点没什么错。。。
原型模式的现实场景
比如要通知几十个客户有买车的实惠信息。
你不会笨到一个个客户去给他单独的写邮件和邮件里面的信息吧。
好一点的做法就是写好一封邮件内容,发给第一个客户。
如果内容发送正常,就上一次发送的邮件信息转发或复制給剩下的几十个客户的邮箱里面。
上面就是一次原型模式的模拟情况。
原型模式的定义
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
原型模式的类图
原型模式设计到三种角色
1.客户角色
该角色提出创建对象的请求。
2.抽象原型角色
该角色是一个抽象角色,通常由一个java接口或抽象类实现,给出所有的具体原型类所需要的接口。
3.具体原型角色
该角色是被复制的对象,必须实现抽象原型接口。
原型模式的优点/缺点
1.性能优化
原型模式使对内存中二进制流的拷贝,要比直接new一个对象性能好,特别使当一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
2.逃避构造函数的约束。
这既是优点,也是缺点,直接在内存中拷贝对象,构造函数是不会执行的,因此减少了约束,但是也有可能造成没有对一些数据继续必要的初始化,这一点要在实际应用中进行权衡考虑。
原型模式的应用场景
1.资源优化场景。
类初始化时需要消化非常多的资源,这个资源包括数据、硬件资源等等,原型模式就能跳过这些步骤。
2.性能和安全要求的场景。
如果通过new来产生一个对象需要非常繁琐的数据准备和访问权限,则可以通过原型模式。
3.一个对象多个修改者的场景。
一个对象需要提供給其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑原型模式拷贝多个对象供调用者使用。
java克隆对象
java中内置了克隆机制。Object类具有一个clone()方法,能够实现对象的克隆。
使一个类支持克隆只需要两步。
1.实现接口Cloneable类
2.覆盖Object的clone()方法,完成对象的克隆操作,通常只需要调用Object的clone()方法即可。
为了使外部能够调用此类的clone()方法,可以将访问修饰符改为public。
原型设计模式的实例
这里就以通知多个客户的情况做示例。
原型模式实例类图
各个接口/类的代码
1.抽象原型角色接口:Cloneable
这是系统的接口类,直接实现它就可以了
2.具体原型角色:Email
- package p5_prototype;
- /**
- * 继承了Cloneable 接口的类
- * 用于完成对象的复制
- * 完成通过自身对象复制出一个新的对象
- */
- public class Email implements Cloneable {
- //邮件的基本信息
- private String receiver; //邮件的接收人
- private String title; //邮件标题
- private String contxt; //邮件内容
- /**
- * 构造方法
- */
- public Email(String title, String contxt) { //因为标题和内容一样
- this.title = title;
- this.contxt = contxt;
- }
- /**
- * 克隆方法
- * 克隆对象的具体实现
- * 覆盖掉原本的clone方法
- * 通过自身对象调用clone方法,可以得到新的对象
- */
- public Email clone() {
- Email email = null;
- try {
- email = (Email) super.clone();
- } catch(CloneNotSupportedException e) {
- e.printStackTrace();
- }
- return email;
- }
- //get和set方法,不管是new出来的对象还是复制出来的对象都是可以调用下面的方法
- public String getReceiver() {
- return receiver;
- }
- public void setReceiver(String receiver) {
- this.receiver = receiver;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getContxt() {
- return contxt;
- }
- public void setContxt(String contxt) {
- this.contxt = contxt;
- }
- }
3.客户角色:BenzClient
- package p5_prototype;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 原型的客户,接手邮件
- */
- public class BenzClient {
- List < String > receiverList = new ArrayList < String > (); //要发送的收件人的集合
- /**
- * 在集合中添加收件人
- */
- public List < String > getEmeilList() {
- receiverList.add("李先生");
- receiverList.add("梁小姐");
- receiverList.add("习先生");
- receiverList.add("大飞机");
- return receiverList;
- }
- /**
- * 发送邮件的方法
- * 模拟发送。。。
- */
- public void sendEmail(Email email) {
- System.out.println("发送邮件給:" + email.getReceiver() + ",标题:" + email.getTitle() + ",内容:" + email.getContxt());
- }
- }
我这里是把客户群体当成是一个对象。
4.原型模式的调用类:PrototypeDemo
- package p5_prototype;
- /**
- * 原型模式的调用者,客户
- */
- public class PrototypeDemo {
- public static void main(String[] srgs) {
- //创建一个Email原型,用来被复制
- Email email = new Email("买车优惠活动", "十一期间买车就送一个超级大娃娃");
- BenzClient client = new BenzClient();//客户对象,接收邮件
- //給所有用户发送邮件
- int num = client.getEmeilList().size();//客户的个数
- for (int i = 0; i < num; i++) {
- Email copyEmail = email.clone();//根据对象复制新的对象
- String receiver = client.getEmeilList().get(i);//获取集合中的收件人
- copyEmail.setReceiver(receiver);//給邮件添加收件人
- client.sendEmail(copyEmail);//发送邮件
- }
- }
- }
程序运行结果:
之前也详细介绍过了java设计模式中的其他四种创建型模式:
建造者模式:http://blog.csdn.net/wenzhi20102321/article/details/78163855
抽象工厂模式:http://blog.csdn.net/wenzhi20102321/article/details/78153437
工厂方法模式:http://blog.csdn.net/wenzhi20102321/article/details/78129065
可以仔细对比一下工厂方法模式和抽象工厂模式,看看概念,看看类图,看看代码,就会明白了。
单例模式:http://blog.csdn.net/wenzhi20102321/article/details/77882203
java 23种设计模式介绍:http://blog.csdn.net/wenzhi20102321/article/details/54601909
国庆假期马上就要结束了。。。