• 原型模式


    原型模式概念

      该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。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咯

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

    作者:鹏鹏

        

  • 相关阅读:
    防止浏览器记住用户名及密码的简单实用方法
    vb.net如何发送含双引号的字符串。转义双引号
    武神坛任务超详细解说。刷战神任务
    Asp.Net文件和文件夹操作大全
    LINQ 中的 select
    经典.net常用面试题目基础
    福建厦门联通DNS
    jQuery 遍历函数 each
    为什么 内燃机 要 先压缩空气 才能有效的将 热能 转化为 动能 ?
    【哈哈】 这个题能让官科吵几千楼我也是没想到的
  • 原文地址:https://www.cnblogs.com/MaxElephant/p/10728074.html
Copyright © 2020-2023  润新知