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

    原型模式

    • 定义

    原型模式(Prototype),用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。[DP]


    • 优缺点

    优点:

    1. 拷贝对象省下了初始化对象的资源
    2. 复用被拷贝对象的一些共用的值

    缺点:

    1. 需要在类中写clone方法,违法开闭原则
    2. 深拷贝时,需要让类的每一层都支持,复杂
    3. 逃避构造函数的约束

    • 特点
    1. 分深浅拷贝
    2. 浅拷贝的对象不能有引用类型的属性,否则会出现新对象覆盖旧对象
    3. 被拷贝的类需要实现Cloneable类,使用this.clone()复制自己的对象并返回

    • 结构

    Prototype:原型父类

    ConcretePrototype1:子原型类

    ConcretePrototype2:子原型类


    • 代码

    例子:展示深拷贝和浅拷贝的区别,一个校牌类,一个学生类,校牌类持有一个学生类的对象,先创建一个三班 的张三校牌对象,然后拷贝一份,赋值为五班的李四,分别打印。

    • 浅拷贝(注意:注释的代码不用看,是深浅拷贝替换的代码

          客户端调用类

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/21 12:25
     * @ Description:客户端调用类
     */
    public class TestController {
        public void print(){
            SchoolCard p1 = new SchoolCard("三班");
            p1.setStudent(new Student("张三"));
    
            SchoolCard c1 =  p1.Clone();
            c1.setId("五班");
            c1.getStudent().setName("李四");
            
            System.out.println("p1="+p1.getId()+" name="+p1.getStudent().getName());
            System.out.println("c1="+c1.getId()+" name="+c1.getStudent().getName());
        }
    }
    

      校牌类,注释的代码不用看,是深拷贝的代码

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/21 12:27
     * @ Description:被拷贝的类,校牌类
     */
    public class SchoolCard implements Cloneable{
        private String id;
        private Student student;
    
        public SchoolCard(String id){
            this.id = id;
        }
    //    private SchoolCard(Student student){
    //        this.student = student.Clone();
    //    }
    //
    //    public SchoolCard Clone(){
    //        SchoolCard concretePrototype1 = new SchoolCard(this.student);
    //        concretePrototype1.setId(this.getId());
    //        return concretePrototype1;
    //    }
        public SchoolCard Clone(){
            try {
                return (SchoolCard) this.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public void setStudent(Student student) {
            this.student = student;
        }
    
        public Student getStudent() { return student; }
    
        public void setId(String id) { this.id = id; }
    
        public String getId() { return id; }
    }
    

      

     学生类

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/21 13:13
     * @ Description:被拷贝的类,学生类
     */
    public class Student implements Cloneable{
    
    //    public Student Clone(){
    //        try {
    //            return (Student) this.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    
        public Student(String name){
            this.name = name;
        }
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      输出结果:

    p1=三班 name=李四
    c1=五班 name=李四
    

      明明是一个张三一个李四,但是都是李四,这里就是因为引用类型需要深拷贝,否则会覆盖前面的对象。

    • 深拷贝(调用类不变)

          校牌类修改

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/21 12:27
     * @ Description:被拷贝的类,校牌类
     */
    public class SchoolCard implements Cloneable{
        private String id;
        private Student student;
    
        public SchoolCard(String id){
            this.id = id;
        }
        private SchoolCard(Student student){
            this.student = student.Clone();
        }
    
        public SchoolCard Clone(){
            SchoolCard concretePrototype1 = new SchoolCard(this.student);
            concretePrototype1.setId(this.getId());
            return concretePrototype1;
        }
    //    public SchoolCard Clone(){
    //        try {
    //            return (SchoolCard) this.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
        public void setStudent(Student student) { this.student = student; }
    
        public Student getStudent() { return student; }
    
        public void setId(String id) { this.id = id; }
    
        public String getId() { return id; }
    }
    

      学生类修改

    public class Student implements Cloneable{
    
        public Student Clone(){
            try {
                return (Student) this.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public Student(String name){
            this.name = name;
        }
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      输出

    p1=三班 name=张三
    c1=五班 name=李四
    

      perfect


    • 总结

    原型模式虽然可以带节省资源,方便对象的初始化,但是浅拷贝会有覆盖的问题,深拷贝需要一层一层的深入的修改,很复杂。需要根据场景慎重使用

  • 相关阅读:
    你看懂了程序员的这些笑话吗?
    SharePoint 2013 Designer 自己定义操作菜单
    Ubuntu下用glade和GTK+开发C语言界面程序(三)——学习make的使用方法
    【九】注入框架RoboGuice使用:(Your First Injected Service and BroadcastReceiver)
    LeetCode 122 Best Time to Buy and Sell Stock II
    Cocos2d-x 3.1.1 学习日志6--30分钟了解C++11新特性
    HDU 4914 Linear recursive sequence(矩阵乘法递推的优化)
    TS4
    angularjs1-过滤器
    angularjs1- ng-include
  • 原文地址:https://www.cnblogs.com/fonxi/p/10909228.html
Copyright © 2011-2022 走看看