zoukankan      html  css  js  c++  java
  • 设计模式:原型模式

    定义

    原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

    原型模式是直接基于内存二进制流进行复制,不调用构造函数,新对象的创建时间大大缩短。

    Jdk浅克隆

    jdk中,不需要手动创建原型接口,因为jdk中已经内置了Cloneable原型接口,自定义的原型类只需要实现该接口并重写clone方法即可完成类的复制。

    //setter getter tostring省略
    public class Prototype implements Cloneable{
    
        private String name;
    
        private Integer age;
    
        private Date date;
    
        //注意clone需要改成public修饰
        @Override
        public Prototype clone() throws CloneNotSupportedException {
            return (Prototype)super.clone();
        }
    
    }
    

    浅克隆测试:

        public static void main(String[] args) throws CloneNotSupportedException {
            Prototype prototype = new Prototype();
            prototype.setAge(1);
            prototype.setName("wj");
            prototype.setDate(new Date());
    
    
            Prototype clone = prototype.clone();
            System.out.println(clone);
            System.out.println(prototype);
    
            clone.getDate().setTime(0);
            System.out.println(clone);
            System.out.println(prototype);
        }
    

    image-20201225105002215

    我们发现:修改了克隆类的引用对象后,原对象也发生修改。

    原因:类中存在引用对象属性,则原型对象与克隆对象的该属性会只想同一对象的引用。

    Jdk浅克隆升级版(深克隆)

    public class Prototype implements Cloneable{
    
        private String name;
    
        private Integer age;
    
        private Date date;
    
        @Override
        public Prototype clone() throws CloneNotSupportedException {
            Prototype clone = (Prototype)super.clone();
            Date dateClone = (Date)clone.getDate().clone();
            clone.setDate(dateClone);
            return clone;
        }
    }
    

    再使用上述方法进行测试:

    image-20201225110007490

    发现修改了clone对象,原对象没有修改。这是因为再super.clone()后,手动给克隆对象的相关属性分配给另一块内存。

    不过有一个弊端:当原型对象中有很多引用属性的时候,手动分配十分麻烦,并且引用属性也要重写clone接口。

    序列化实现深克隆

    需要实现Cloneable,Serializable

    public class Prototype implements Cloneable,Serializable {
    
        private String name;
    
        private Integer age;
    
        private Date date;
    
        @Override
        public Prototype clone() throws CloneNotSupportedException {
    
            try{
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(this);
    
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bis);
                return (Prototype)ois.readObject();
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
    }
    

    从结果上看,实现了深克隆。

    image-20201225112535432

    克隆破坏单例模式

    如果单例对象实现了克隆接口,然后我们重写了clone方法并调用,这样会创建出一个新的单例对象,破坏了单例模式。

    解决方案如下:

    • 单例对象不实现Cloneable接口

    • 重写clone方法:

      @Override
      public Prototype clone(){
          return instance;//instance 就是单例对象,只需要直接返回即可
      }
      
  • 相关阅读:
    前端工程化之动态数据代理
    webapp开发之需要知道的css细节
    html-webpack-plugin详解
    file-loader引起的html-webpack-plugin坑
    浅谈react受控组件与非受控组件
    React创建组件的三种方式及其区别
    react项目开发中遇到的问题
    css伪元素:before和:after用法详解
    python之文件操作
    python之range和xrange
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14188382.html
Copyright © 2011-2022 走看看