美文网首页
设计模式之原型模式

设计模式之原型模式

作者: Tinyspot | 来源:发表于2023-02-07 21:24 被阅读0次

    1. 原型模式

    • 对原型进行拷贝来创建新对象
    • 原型模式的两种实现方法
      • 浅拷贝
      • 深拷贝

    1.2 核心组成

    • IPrototype
    • ConcretePrototype
    • Client

    1.3 应用场景

    • 创建新对象成本较大,新的对象可以通过原型模式对已有对象进行复制来获得

    1.4 浅拷贝与深拷贝区别

    • 浅拷贝得到的对象跟原始对象共享数据,而深拷贝会复制数据本身
    • 浅拷贝只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归地复制引用对象,以及引用对象的引用对象……而深拷贝得到的是一份完完全全独立的对象

    2. 浅拷贝

    • 实现 Cloneable 接口
    • 重写 clone()
    • 基本数据类型可以达到完全复制,引用数据类型不可以,因为引用数据类型仅仅是拷贝了一份引用
    public void demo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("AAA");
        list.add("BBB");
    
        Object copyList = list.clone();
        System.out.println(copyList == list);
        System.out.println(copyList);
        // 结果是false, 但内容是一样的
    }
    

    2.2 对象复制

    @Test
    public void test() {
        Course course = new Course("English");
        Student student = new Student("Tinyspot", 20, course);
    
        Student stu2 = new Student();
        stu2.setName(student.getName());
        stu2.setAge(student.getAge());
        stu2.setCourse(student.getCourse());
    
        student.setName("222");
        student.setAge(22);
        student.getCourse().setTitle("Chinese");
        // or course.setTitle("Chinese");
        System.out.println(student.getCourse() == stu2.getCourse()); // true
    }
    

    打印对象:
    student: Student(name=222, age=22, course=Course(title=Chinese))
    stu2: Student(name=Tinyspot, age=20, course=Course(title=Chinese))

    2.3 浅拷贝示例

    • 浅拷贝的引用类型会随原型对象(拷贝对象)改变而改变
    • 实现 Cloneable 接口
    @Test
    public void test() throws CloneNotSupportedException {
        Student student = new Student("Tinyspot", 20, new Course("English"));
        Student stuCopy = student.clone();
    
        student.setAge(22);
        stuCopy.getCourse().setTitle("Chinese");
    }
    

    打印对象:
    student: Student(name=Tinyspot, age=22, course=Course(title=Chinese))
    stuCopy: Student(name=Tinyspot, age=20, course=Course(title=Chinese))

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student implements Cloneable {
        private String name;
        private Integer age;
        private Course course;
    
        @Override
        public Student clone() throws CloneNotSupportedException {
            return (Student) super.clone();
        }
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Course {
        private String title;
    }
    

    3. 深拷贝

    • 递归拷贝对象、对象的引用对象以及引用对象的引用对象……直到要拷贝的对象只包含基本数据类型数据,没有引用对象为止

    3.1 实现方式一

    • 引用类型也实现Cloneable, 重写 clone()
    • 当对象之间存在多重嵌套引用,每一层对象对应的类都必须支持深克隆
    @Test
    public void test() throws CloneNotSupportedException {
        Student student = new Student("Tinyspot", 20, new Course("English"));
        Student stuCopy = student.clone();
        
        student.setAge(22);
        student.getCourse().setTitle("Chinese");
    }
    

    打印对象:
    student: Student(name=Tinyspot, age=22, course=Course(title=Chinese))
    stuCopy: Student(name=Tinyspot, age=20, course=Course(title=English))

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student implements Cloneable {
        private String name;
        private Integer age;
        private Course course;
    
        @Override
        public Student clone() throws CloneNotSupportedException {
            Student student = (Student) super.clone();
            // 将拷贝出的对象赋给成员变量
            // or student.course = this.course.clone();
            student.setCourse(this.course.clone());
            return student;
        }
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Course implements Cloneable {
        private String title;
    
        @Override
        public Course clone() throws CloneNotSupportedException {
            return (Course) super.clone();
        }
    }
    

    3.2 实现方式二

    • 先将对象序列化,然后再反序列化成新的对象
    • Serializable 读取二进制流
    @Test
    public void test() throws CloneNotSupportedException {
        Person person = new Person();
        person.setName("Tinyspot");
        person.getList().add("AAA");
    
        // 测试浅拷贝
        Person personCopy = person.clone();
    
        person.setName("222");
        person.getList().add("BBB");
        // or personCopy.getList().add("BBB");
    
        System.out.println("person: " + person);
        System.out.println("personCopy: " + personCopy);
        System.out.println(person.getList() == personCopy.getList()); // true
    }
    

    打印对象:
    person: Person(name=222, age=null, list=[AAA, BBB])
    personCopy: Person(name=Tinyspot, age=null, list=[AAA, BBB])

    @Test
    public void test() {
        Person person = new Person();
        person.setName("Tinyspot");
        person.getList().add("AAA");
    
        // 测试深拷贝
        Person personCopy = person.deepClone();
        personCopy.getList().add("BBB");
    }
    

    打印对象
    person: Person(name=Tinyspot, age=null, list=[AAA])
    personCopy: Person(name=Tinyspot, age=null, list=[AAA, BBB])

    相关文章

      网友评论

          本文标题:设计模式之原型模式

          本文链接:https://www.haomeiwen.com/subject/iaufkdtx.html