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

    原型模式

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

      优势:创建对象效率高(直接克隆,避免重新执行构造过程步骤)

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

    原型模式实现

      实现 Cloneable 接口,重写 clone 方法;

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

    1、浅拷贝实现:

    public class Sheep implements Cloneable
    {
        private String sname;
        private Date birthday;
    
        public Sheep()
        {
        }
    
        public Sheep(String sname, Date birthday)
        {
            this.sname = sname;
            this.birthday = birthday;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException
        {
         Object object = super.clone();
    return object; } //省略 getter 和 setter 方法 }

    测试类,如下:

    public class Client
    {
        public static void main(String[] args) throws CloneNotSupportedException
        {
            Date date = new Date(111111111111L);
            Sheep sheep1 = new Sheep("多利", date);
            System.out.println(sheep1);
            System.out.println("sheep1:  " + sheep1.getSname() + ":" + sheep1.getBirthday());
            System.out.println("------------------------------");
    
            Sheep sheep2 = (Sheep) sheep1.clone();
            System.out.println(sheep2);
            System.out.println("sheep2:  " + sheep2.getSname() + ":" + sheep2.getBirthday());
            System.out.println("----改变date后---");
            date.setTime(1235313478966L);  //改变date对象的值
    
            System.out.println("sheep2:  " + sheep2.getSname() + ":" + sheep2.getBirthday());
        }
    }

    结果如下:

      com.yufeng.prototype.Sheep@60e53b93
      sheep1: 多利:Tue Jul 10 08:11:51 CST 1973
      ------------------------------
      com.yufeng.prototype.Sheep@5e481248
      sheep2: 多利:Tue Jul 10 08:11:51 CST 1973
      ----改变date后---
      sheep2: 多利:Sun Feb 22 22:37:58 CST 2009

    结果分析:

      通过sheep1的clone()方法克隆的对象 sheep2,接着改变date对象的值之后,sheep2 对象中 birthday 发生了变化;说明 sheep1 和 sheep2 指向了同一个 date 对象,所以为浅拷贝

    2、深拷贝实现:

    方式一:属性也进行clone

    实现 Cloneable 接口,重写clone()方法

    public class Sheep implements Cloneable
    {
        private String sname;
        private Date birthday;
    
        public Sheep()
        {
        }
    
        public Sheep(String sname, Date birthday)
        {
            this.sname = sname;
            this.birthday = birthday;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException
        {
            Object object = super.clone(); 
    
            //添加如下代码实现深拷贝(deep clone)
            Sheep sheep = (Sheep) object;
            sheep.setBirthday((Date) this.birthday.clone());
            return object;
        }
    
        //省略 getter 和 setter 方法
    }

    结果如下:

      com.yufeng.prototype.Sheep@60e53b93
      sheep1: 多利:Tue Jul 10 08:11:51 CST 1973
      ------------------------------
      com.yufeng.prototype.Sheep@5e481248
      sheep2: 多利:Tue Jul 10 08:11:51 CST 1973
      ----改变date后---
      sheep2: 多利:Tue Jul 10 08:11:51 CST 1973

    方式二:序列化和反序列化实现深拷贝

    实现 Cloneable 接口,重写clone()方法; 实现 Serializable 接口

    public class Sheep implements Cloneable, Serializable
    {
        private String sname;
        private Date birthday;
    
        public Sheep()
        {
        }
    
        public Sheep(String sname, Date birthday)
        {
            this.sname = sname;
            this.birthday = birthday;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException
        {
            Object object = super.clone(); 
            return object;
        }
    
        // 省略 getter 和 setter 方法
    }

    测试类,代码如下:

    public class Client2
    {
        public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException
        {
            Date date = new Date(111111111111L);
            Sheep sheep1 = new Sheep("多利", date);
            System.out.println(sheep1);
            System.out.println("sheep1:  " + sheep1.getSname() + ":" + sheep1.getBirthday());
            System.out.println("------------------------------");
    
            //Sheep sheep2 = (Sheep) sheep1.clone();
            //使用序列化和反序列化实现深克隆
            //序列化到字节数组中
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(sheep1);
            byte[] bytes = bos.toByteArray();
    
            //反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            Sheep sheep2 = (Sheep) ois.readObject();
    
            System.out.println(sheep2);
            System.out.println("sheep2:  " + sheep2.getSname() + ":" + sheep2.getBirthday());
            System.out.println("----改变date后---");
            date.setTime(1235313478966L);
    
            System.out.println("sheep2:  " + sheep2.getSname() + ":" + sheep2.getBirthday());
        }
    }

    结果如下:

      com.yufeng.prototype.Sheep@60e53b93
      sheep1: 多利:Tue Jul 10 08:11:51 CST 1973
      ------------------------------
      com.yufeng.prototype.Sheep@5e481248
      sheep2: 多利:Tue Jul 10 08:11:51 CST 1973
      ----改变date后---
      sheep2: 多利:Tue Jul 10 08:11:51 CST 1973

  • 相关阅读:
    Android中layout_gravity和gravity的区别
    Android基础面试题
    小白学习设计模式之工厂模式
    装饰者模式视频示例
    小白学习设计模式之装饰者模式
    利用poi来向execl中写入对象
    java利用poi来读取execl表格返回对象
    java小白设计模式之观察者模式
    小白学习java设计模式之策略模式
    如何理解java是一个面向对象的语言?(转自Hollis的直面java)
  • 原文地址:https://www.cnblogs.com/yufeng218/p/10074162.html
Copyright © 2011-2022 走看看