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

    原型模式是创建型模式的一种,其特点在于通过 “复制” 一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的 “原型”,这个原型是可定制的。

    类图

    代码实现

    用于测试的 JavaBean:

    package com.huey.pattern.prototype;
    
    import java.io.Serializable;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public class TestBean implements Serializable {
        
        /**
         * 
         */
        private static final long serialVersionUID = -2351683706932774662L;
        
        @Getter @Setter
        private String testValue;
    
    }

    抽象原型:

    package com.huey.pattern.prototype;
    
    /**
     * the abstract prototype
     * @author  huey
     * @version 1.0 
     * @created 2015-11-27
     */
    public abstract class Prototype implements Cloneable {
        
        public Prototype() {
            System.out.println("Prototype is constructed.");
        }
        
        @Override
        protected Prototype clone() {
            try {
                return (Prototype) super.clone();
            } catch (Exception e) {
                return null;
            }
        }
    
    }

    具体原型:

    package com.huey.pattern.prototype;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    /**
     * the concrete prototype
     * @author  huey
     * @version 1.0 
     * @created 2015-11-27
     */
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public class ShallowCopyBean extends Prototype {
    
        @Getter @Setter
        private Integer primitiveValue;
        @Getter @Setter
        private TestBean customValue;
        
    }

    单元测试:

    package com.huey.pattern.prototype;
    
    public class ShallowCopyBeanTest {
    
        public static void main(String[] args) {        
            Prototype cloneableBean = new ShallowCopyBean(10, new TestBean("AAA"));
            System.out.println("cloneableBean: " + cloneableBean);
            
            ShallowCopyBean clonedBean = (ShallowCopyBean) cloneableBean.clone();
            clonedBean.setPrimitiveValue(100);
            clonedBean.getCustomValue().setTestValue("BBB");
            System.out.println("cloneableBean: " + cloneableBean);
            System.out.println("clonedBean: " + clonedBean);
        }
        
    }

    结果输出:

    Prototype is constructed.
    cloneableBean: ShallowCopyBean(primitiveValue=10, customValue=TestBean(testValue=AAA))
    cloneableBean: ShallowCopyBean(primitiveValue=10, customValue=TestBean(testValue=BBB))
    clonedBean: ShallowCopyBean(primitiveValue=100, customValue=TestBean(testValue=BBB))

    从输出可以看到,原型只被构造一次。但是这里需要注意当 clonedBean 的引用对象 customVaule 的内容发生改变时,cloneableBean 的 customVaule 也跟着改变。这就是深拷贝与浅拷贝的问题,Java 中,Object 类的 clone 方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。

    深拷贝

    实现深拷贝可以在重写 clone 方法中,对数组、容器对象、引用对象等自己进行拷贝。

    还可以使用一个技巧,就是利用序列化的机制来实现,通过将对象序列化到输出流中,然后将其读回,这样产生的新对象是对现有对象的一个深拷贝。

    代码实现

    可序列化的抽象原型:

    package com.huey.pattern.prototype;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    /**
     * the abstract prototype
     * @author  huey
     * @version 1.0 
     * @created 2015-11-27
     */
    public abstract class SerialCloneable implements Serializable, Cloneable {
    
        /**
         * 
         */
        private static final long serialVersionUID = -2477239830471073680L;
    
        @Override
        protected Object clone() {
            try {
                /**
                 * serialize the object to the output stream
                 */
                ByteArrayOutputStream bout = new ByteArrayOutputStream();
                ObjectOutputStream output = new ObjectOutputStream(bout);
                output.writeObject(this);
                output.close();
                
                /**
                 * deserialize the object from the input stream
                 */
                ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
                ObjectInputStream input = new ObjectInputStream(bin);
                Object result = input.readObject(); 
                input.close();
                
                return result;
            } catch (Exception e) {
                return null;
            }
        }
    }

    具体原型:

    package com.huey.pattern.prototype;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    /**
     * the concrete prototype
     * @author  huey
     * @version 1.0 
     * @created 2015-11-27
     */
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public class DeepCopyBean extends SerialCloneable {
    
        /**
         * 
         */
        private static final long serialVersionUID = -959424582381713341L;
        
        @Getter @Setter
        private Integer primitiveValue;
        @Getter @Setter
        private TestBean customValue;
        
    }

    单元测试:

    package com.huey.pattern.prototype;
    
    public class DeepCopyBeanTest {
        
        public static void main(String[] args) {
            
            SerialCloneable cloneableBean = new DeepCopyBean(10, new TestBean("AAA"));
            System.out.println("cloneableBean: " + cloneableBean);
            
            DeepCopyBean clonedBean = (DeepCopyBean) cloneableBean.clone();
            clonedBean.setPrimitiveValue(100);
            clonedBean.getCustomValue().setTestValue("BBB");
            System.out.println("cloneableBean: " + cloneableBean);
            System.out.println("clonedBean: " + clonedBean);
        }
    
    }

    结果输出:

    cloneableBean: DeepCopyBean(primitiveValue=10, customValue=TestBean(testValue=AAA))
    cloneableBean: DeepCopyBean(primitiveValue=10, customValue=TestBean(testValue=AAA))
    clonedBean: DeepCopyBean(primitiveValue=100, customValue=TestBean(testValue=BBB))

    从输出可以看到,clonedBean 的引用对象 customVaule 的内容发生改变时,不会影响到 cloneableBean 的 customVaule。

    原型模式的适用场合

    1) 产生对象过程比较复杂,初始化需要许多资源时;

    2) 希望框架原型和产生对象分开时;

    3) 同一个对象可能会供其他调用者使用访问时。

  • 相关阅读:
    搭建非域AlwaysOn win2016+SQL2016
    从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)
    从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
    从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
    从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)
    四、基于Windows 2012配置SQL Server 2014 AlwaysOn
    三、安装SQLserver 2014(For AlwaysOn)
    二、 Windows 2012配置故障转移(For SQLServer 2014 AlwaysOn)
    Mybatis-SQL语句构建器类及日志
    Mybatis-JavaAPI
  • 原文地址:https://www.cnblogs.com/huey/p/5001374.html
Copyright © 2011-2022 走看看