设计模式(四)原型模式

原型模式:通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。

优势:效率高(直接克隆,避免了重新执行构造步骤)。

克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。


原型模式实现:

Cloneable接口和clone方法。

Prototype模式中实现起来最困难的地方就是内存复制操作,所幸在Java中提供了clone()方法替我们做了绝大部分事情。


浅复制和深复制:

例:浅复制

 定义一个Sheep类:

 1 package com.ztq.prototype;
 2 
 3 import java.util.Date;
 4 
 5 public class Sheep implements Cloneable{
 6     private String sname;
 7     private Date birthday;
 8     
 9     @Override
10     protected Object clone() throws CloneNotSupportedException {
11         Object obj = super.clone(); //直接调用Object对象的clone()方法
12         return obj;
13     }
14 
15     public String getSname() {
16         return sname;
17     }
18 
19     public void setSname(String sname) {
20         this.sname = sname;
21     }
22 
23     public Date getBirthday() {
24         return birthday;
25     }
26 
27     public void setBirthday(Date birthday) {
28         this.birthday = birthday;
29     }
30 
31     public Sheep(String sname, Date birthday) {
32         super();
33         this.sname = sname;
34         this.birthday = birthday;
35     }
36     
37     public Sheep(){}
38 }

测试类:

 1 package com.ztq.prototype;
 2 
 3 import java.util.Date;
 4 
 5 /***
 6  * 测试原型模式(浅复制)
 7  * @author ZTQ
 8  *
 9  */
10 public class Client2 {
11     public static void main(String[] args) throws CloneNotSupportedException {
12         Date date = new Date(123123123123L);
13         Sheep s1 = new Sheep("aa", date);
14         Sheep s2 = (Sheep)s1.clone();
15         
16         System.out.println(s1.getBirthday());
17         
18         date.setTime(234234234L);
19         
20         System.out.println(s1.getBirthday());
21         System.out.println(s2.getBirthday());
22     }
23 }

打印结果:

Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Sun Jan 04 01:03:54 GMT+08:00 1970

可见,s2克隆的s1,更改时间后,s2的birthday属性也跟着改变了。

深复制:


将重新的clone方法中添加代码:

 1 @Override
 2     protected Object clone() throws CloneNotSupportedException {
 3         Object obj = super.clone(); //直接调用Object对象的clone()方法
 4         
 5         //添加如下代码实现深复制
 6         Sheep s = (Sheep)obj;
 7         s.birthday = (Date)this.birthday.clone();
 8         
 9         return obj;
10     }

打印结果:

Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Mon Nov 26 08:52:03 GMT+08:00 1973

时间改变后,s2的birthday属性并没有随之改变。

序列化和反序列化实现深复制:

 1 public class Client2 {
 2     public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
 3         Date date = new Date(123123123123L);
 4         Sheep s1 = new Sheep("aa", date);
 5         System.out.println(s1);
 6         System.out.println(s1.getSname());
 7         System.out.println(s1.getBirthday());
 8 //        Sheep s2 = (Sheep)s1.clone();
 9 //        使用序列化和反序列化实现深复制
10         ByteArrayOutputStream bos = new ByteArrayOutputStream();
11         ObjectOutputStream oos = new ObjectOutputStream(bos);
12         oos.writeObject(s1);
13         byte[] bytes = bos.toByteArray();
14         
15         ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
16         ObjectInputStream ois = new ObjectInputStream(bis);
17         Sheep s2 = (Sheep)ois.readObject();  //克隆好的对象
18         
19         date.setTime(234234234L);  
20         
21         System.out.println(s1.getBirthday());
22         System.out.println(s2.getBirthday());
23     }

 打印结果:

com.ztq.prototype.Sheep@133c5982
aa
Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Mon Nov 26 08:52:03 GMT+08:00 1973

开发中的应用场景:

——原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。

  spring中bean的创建实际就是两种:单例模式和原型模式。(当然,原型模式需要和工厂模式搭配起来)

总结:

创建者模式:都是用来帮助我们创建对象的。

——单例模式:

  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

——工厂模式:

  简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)

  工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)

  抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

——建造者模式:

  分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责),从而可以构造出复杂的对象。

——原型模式:

  通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

原文地址:https://www.cnblogs.com/zhangtianq/p/6006120.html