zoukankan      html  css  js  c++  java
  • 设计模式(四)原型模式

    原型模式:通过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产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

  • 相关阅读:
    OpenWrt/LEDE 没有slabtop命令
    OpenWrt/LEDE 没有/proc/slabinfo文件
    泰坦陨落2 origin安装时vc++runtime没有安装成功错误
    OpenWrt/LEDE中使用qt库
    椭圆曲线加密(ECC):域和离散对数
    batman-adv使用中修改一跳惩罚,batctl无法修改hop_penalty
    VMnet8设置ping通外网
    支持自动水平拆分的高性能分布式数据库TDSQL
    cronsun是替换 crontab 一个不错的选择
    MySQL 的 20+ 条最佳实践
  • 原文地址:https://www.cnblogs.com/zhangtianq/p/6006120.html
Copyright © 2011-2022 走看看