zoukankan      html  css  js  c++  java
  • 原型模式之深浅克隆

    原型模式跟其他的创建型模式不同,它要做的是对特定的对象进行克隆。所谓克隆就是根据当前对象的特征,完全的复制一份出来。原型模式分为深拷贝和浅拷贝。不管是深拷贝和浅拷贝对于对象中的基本数据类型和String类型都会完全的复制,区别就是在复制对象中的其他引用类型时,浅拷贝只会复制对象中引用类型的地址,而不会完全的克隆一份。

    浅拷贝

    下面测试代码,User类中有Integer类型和String类型以及一个Father对象。User类对外提供的copy()方法使用了Object的clone()方法,就完成了对象的复制。需要注意的是,使用clone()方法的类需要实现Cloneable接口,该接口只是一个标记接口。最终的测试我们改变了克隆出来的对象的三个属性,原对象的Integer和String类型属性没有收到影响,而Father属性则收到了影响。这表明,克隆出来的对象并没有完全的复制,对于引用类型只是复制了其栈的引用。

    package prototype_k;/*
     * @auther 顶风少年
     * @mail dfsn19970313@foxmail.com
     * @date 2020-01-15 17:49
     * @notify
     * @version 1.0
     */
    
    public class User implements Cloneable {
        private String name;
        private Integer age;
        private Father father;
    
        public User(String name, Integer age, Father father) {
            this.name = name;
            this.age = age;
            this.father = father;
        }
    
        public User copy() throws Exception {
            return (User) this.clone();
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public void setFather(Father father) {
            this.father = father;
        }
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public Father getFather() {
            return father;
        }
    }
    View Code
    package prototype_k;/*
    * @auther 顶风少年 
    * @mail dfsn19970313@foxmail.com
    * @date 2020-01-15 17:50
    * @notify 
    * @version 1.0
    */
    
    
    public class Father {
        private String name;
    
        public Father(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    View Code
    package prototype_k;/*
     * @auther 顶风少年
     * @mail dfsn19970313@foxmail.com
     * @date 2020-01-15 17:49
     * @notify
     * @version 1.0
     */
    
    public class Main {
        public static void main(String[] args) throws Exception {
            User user = new User("张三", 1, new Father("张爸爸"));
            User cloneUser = user.copy();
            System.out.println(user == cloneUser);//false
            cloneUser.setName("李四");
            cloneUser.setAge(2);
            Father father = cloneUser.getFather();
            father.setName("李爸爸");
    
            System.out.println(user.getName());//张三
            System.out.println(user.getAge());//1
            System.out.println(user.getFather().getName());//李爸爸
        }
    }
    View Code

    深拷贝

    而深度拷贝需要使用对象序列化和反序列化,这个过程叫做冷冻和解冻。很好明白的,当一个对象被读取到了流里,那么流里的对象已经不是对象了,只是二进制数据,表明完全和原有的对象切断了联系。最后解冻则是一个完完全全的新的对象。需要注意的是被序列化的对象必须实现Serializable标记接口,对象内的其他引用对象也需要实现。

    package prototype_k;/*
     * @auther 顶风少年
     * @mail dfsn19970313@foxmail.com
     * @date 2020-01-15 17:49
     * @notify
     * @version 1.0
     */
    
    import java.io.*;
    
    public class User2 implements Serializable{
        private String name;
        private Integer age;
        private Father father;
    
        public User2(String name, Integer age, Father father) {
            this.name = name;
            this.age = age;
            this.father = father;
        }
    
        public User2 copy() throws Exception {
            ByteArrayOutputStream byteInputStream = new ByteArrayOutputStream();
            ObjectOutputStream outputStream = new ObjectOutputStream(byteInputStream);
            outputStream.writeObject(this);
    
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteInputStream.toByteArray());
            ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream);
            Object object = inputStream.readObject();
    
    
            return (User2) object;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public void setFather(Father father) {
            this.father = father;
        }
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public Father getFather() {
            return father;
        }
    }
    View Code
    package prototype_k;/*
    * @auther 顶风少年 
    * @mail dfsn19970313@foxmail.com
    * @date 2020-01-15 17:50
    * @notify 
    * @version 1.0
    */
    
    import java.io.Serializable;
    
    public class Father implements Serializable {
        private String name;
    
        public Father(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    View Code
    package prototype_k;/*
    * @auther 顶风少年 
    * @mail dfsn19970313@foxmail.com
    * @date 2020-01-15 18:46
    * @notify 
    * @version 1.0
    */
    public class Main2 {
        public static void main(String[] args)throws Exception {
            User2 user = new User2("张三", 1, new Father("张爸爸"));
            User2 cloneUser = user.copy();
            System.out.println(user == cloneUser);
            cloneUser.setName("李四");
            cloneUser.setAge(2);
            Father father = cloneUser.getFather();
            father.setName("李爸爸");
    
            System.out.println(user.getName());
            System.out.println(user.getAge());
            System.out.println(user.getFather().getName());
        }
    
    
    }
    View Code
  • 相关阅读:
    [翻译] DZNSegmentedControl
    GONMarkupParser的使用
    使用@selector模仿代理功能降低代码耦合度
    编译并导入OpenSSL
    [翻译] TLTagsControl
    [控件] BookTextView
    [控件] AngleGradientView
    【转】jQuery属性过滤选择器
    【转】ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
    【转】PHP----JS相互调用
  • 原文地址:https://www.cnblogs.com/zumengjie/p/12198362.html
Copyright © 2011-2022 走看看