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

    原型模式概念

      该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。java中复制通过clone()实现的。clone中涉及深、浅复制。深、浅复制的概念如下:

      ⑴浅复制(浅克隆) 

          被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址

      ⑵深复制(深克隆) 

          被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。 

    原型模式代码

    package com.roc.prototype;
    
    import java.io.Serializable;
    /**
     * 原型模式   程序员
     * @author liaowp
     *
     */
    public class Programmer implements Serializable,Cloneable{
        
        /**
         * 
         */
        private static final long serialVersionUID = 3078949912404836178L;
        
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Programmer clone() throws CloneNotSupportedException {  
            Programmer proto = (Programmer) super.clone();  
            return proto;  
        }  
    }

    下面写一个浅复制的例子

    package com.roc.prototype;
    /**
     * 地址
     * @author liaowp
     *
     */
    public class Address{
    
        private String province;//
        
        private String city;//
        
        public Address(String province,String city){
            this.province=province;
            this.city=city;
        }
    
        public String getProvince() {
            return province;
        }
    
        public void setProvince(String province) {
            this.province = province;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        } 
    }
    package com.roc.prototype;
    
    /**
     * 原型模式   程序员
     * @author liaowp
     *
     */
    public class Programmer implements Cloneable{
        
        
        private String name;//名字
        
        private  Address address;
    
        public Programmer(String name,Address address){
            this.name=name;
            this.address=address;
        }
        
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Object clone() throws CloneNotSupportedException {  
            Programmer proto = (Programmer) super.clone();  
            return proto;  
        }  
        
    }
    package com.roc.prototype;
    /**
     * 原型模式
     * @author liaowp
     *
     */
    public class Client {
        
        public static void main(String[] args) throws CloneNotSupportedException {    
            //浅复制复制
            Address address=new Address("jx","gz");
            Programmer a=new Programmer("liaowp",address);
            a.setAddress(new Address("jx", "gz"));
            a.setName("liaowp");
            Programmer b=(Programmer) a.clone();
            b.setName("pwl");
            b.getAddress().setProvince("bj");
            System.err.println(b.getName()+b.getAddress().getProvince());
            System.err.println(a.getName()+a.getAddress().getProvince());    
        }
    }

      输出结果:pwlbj

                       liaowpbj

      可以看出来对象并复制,依然使用的是同一个引用。其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。下面看深复制的写法,深复制有2种写法,一种是对象实现Cloneable,另外一种是二进制流。我都一起写了。

    package com.roc.prototype;
    
    /**
     * 原型模式   程序员
     * @author liaowp
     *
     */
    public class Programmer implements Cloneable{
        
        
        private String name;//名字
        
        private  Address address;
    
        public Programmer(String name,Address address){
            this.name=name;
            this.address=address;
        }
        
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Object clone() throws CloneNotSupportedException {  
            Programmer proto = (Programmer) super.clone();  
            proto.address=(Address) address.clone();
         return proto; } }
    package com.roc.prototype;
    /**
     * 地址
     * @author liaowp
     *
     */
    public class Address implements Cloneable{
    
        private String province;//
        
        private String city;//
        
        public Object clone(){
            
            Address address = null;
            try {
                address = (Address) super.clone();
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return address;
        }
      public Address(String province,String city){ this.province=province; this.city=city; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; }

        /* 深复制 */ 二进制的写法,需要类序列化

        public Object deepClone() throws IOException, ClassNotFoundException {

          /* 写入当前对象的二进制流 */
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          ObjectOutputStream oos = new ObjectOutputStream(bos);
          oos.writeObject(this);

          /* 读出二进制流产生的新对象 */
          ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
          ObjectInputStream ois = new ObjectInputStream(bis);
          return ois.readObject();
      }

    }

    package com.roc.prototype;
    /**
     * 原型模式
     * @author liaowp
     *
     */
    public class Client {
        
        public static void main(String[] args) throws CloneNotSupportedException {
            //浅复制复制
            Address address=new Address("jx","gz");
            Programmer a=new Programmer("liaowp",address);
            a.setAddress(new Address("jx", "gz"));
            a.setName("liaowp");
            Programmer b=(Programmer) a.clone();
            b.setName("pwl");
            b.getAddress().setProvince("bj");
            System.err.println(b.getName()+b.getAddress().getProvince());
            System.err.println(a.getName()+a.getAddress().getProvince());
        }
    }

    结果:pwlbj

        liaowpjx

       拷贝还有2个知识点,对象拷贝时,类的构造函数是不会被执行的。一个实现了 Cloneable 并重写了 clone 方法的类 Programmer,有一个无参构造或有参构造 ,通过 new 关键字产生了一个对象 A,再然后通过 A.clone()方式产生了一个新的对象 T,那么在对象拷贝时构造函数是不会被执行的。即拷贝的过程中只执行一次构造方法。

      Clone 与 final 两对冤家。对象的 clone 与对象内的 final 属性是由冲突.在上面的Programmer类中修改为private final Address address;去掉get,set方法, proto.address=(Address) address.clone();这一句就会报错: proto.address=(Address) address.clone();final类型不能重新设置值。解决办法就是删除掉fina咯

      深拷贝和浅拷贝建议不要混合使用,一个类中某些引用使用深拷贝某些引用使用浅拷贝,这是一种非常差的设计,特别是是在涉及到类的继承,父类有几个引用的情况就非常的复杂,建议深拷贝和浅拷贝分开实现。

  • 相关阅读:
    Exp4 恶意代码分析 Week6
    Exp3 免杀原理与实践 Week5
    Exp2 后门原理与实践 Week4
    Exp1 PC平台逆向破解 Week3
    Exp0 Kali安装 Week1
    2018-2019-2 《网络对抗技术》Exp9 WebGoat 20165326
    2018-2019-2 《网络对抗技术》Exp8 Web基础 20165326
    2018-2019-2 《网络对抗技术》Exp7 网络欺诈防范 20165326
    2018-2019-2 《网络对抗技术》Exp6 信息搜集与漏洞扫描 20165326
    2018-2019-2 《网络对抗技术》Exp5 MSF基础应用 20165326
  • 原文地址:https://www.cnblogs.com/liaoweipeng/p/5768645.html
Copyright © 2011-2022 走看看