• 趣解设计模式之《小王的学习秘籍》


    〇、小故事

    小王是学校的学霸,凭借着自己的天赋以及对于学习的刻苦,每次考试都能排到年级第一名。但是,他所在的班级总成绩却不高,在所有班级中,属于中游水平。老师希望通过小王的贡献,能否帮助整个班级同学分数都有一个提升

    老师跟小王提出了这个建议后,小王也很痛快就答应了。然后,利用周六和周日两天时间,将本周的一些重点和难点知识,以及他自己对于某些知识的理解小窍门都总结了出来,一共写了20多页的总结笔记

    周一上学,大家都争着抢着去借阅小王的“学习秘籍”,甚至很多同学都开始手抄了起来。20多页的内容,纯手抄得需要好长时间,这时候,小王跟同学们说,“大家别手抄了,太麻烦了,我去楼下的打印社,给同学们每人打印一份”。

    就这样,大概用了20分钟不到的时间,就给全班50多名同学每人打印了一份。大家开心的复习了起来,最后,通过小王同学每周总结的“学习秘籍”,他们班级的总成绩跃升成为了年级第一,大家开心极了!

    通过上面的例子我们发现,如果大家手抄一份学习秘籍,假设每人平均需要1个小时的话,那么班级50名同学,都抄完就需要50个小时了。但是,如果复印的话,一页50份如果需要1分钟,那么20页需要20分钟就可以了。同样的创建50份学习秘籍,从50小时缩短为20分钟,这就是我们今天要介绍的设计模式的魅力——原型模式

    一、模式定义

    原型模式Prototype Pattern

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。也就是说,这种不通过new关键字来产生一个对象,而是通过对象复制(Java中的clone反序列化)来实现的模式,就叫做原型模式

    二、模式类图

    原型模式的类图比较简单,只需要clone方法和实现clone方法即可,客户端如果需要去创建实例,则通过调用clone就可以了。具体类图如下所示:

    三、原型模式的应用场景

    3.1> 原型模式的特点

    性能优良

    原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环内产生大量的对象时,原型模式可能更好地体现其优点。

    逃避构造函数的约束

    直接在内存中拷贝,构造函数是不会执行的。

    3.2> 原型模式的使用场景

    资源优化场景

    类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等等。

    性能和安全要求的场景

    通过new产生一个对象需要非常繁琐的数据准备或访问权限,这时则可以使用原型模式。

    一个对象多个修改者的场景

    一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用

    四、原型模式的注意事项

    4.1> 构造函数不会被执行

    验证通过clone()方法不会触发构造函数的执行Prototype.java

    1. public class Prototype implements Cloneable {
    2.     public static void main(String[] args) {
    3.         Prototype prototype = new Prototype();
    4.         
    5.         /** 通过clone方法创建的Prototype对象不会执行构造方法 */
    6.         Prototype clonePrototype = prototype.clone();
    7.     }
    8.     public Prototype() {
    9.         System.out.println("-----Prototype的构造方法被执行了!-----");
    10.     }
    11.     @Override
    12.     protected Prototype clone() {
    13.         try {
    14.             return (Prototype)super.clone();
    15.         } catch (CloneNotSupportedException e) {
    16.             e.printStackTrace();
    17.         }
    18.         return null;
    19.     }
    20. }

    执行结果如下所示

    1. -----Prototype的构造方法被执行了!-----
    2. Process finished with exit code 0

    4.2> 浅拷贝&深拷贝

    实现浅拷贝与深拷贝Prototype1.java

    1. @Data
    2. public class Prototype1 implements Cloneable {
    3.     private String name;
    4.     private List<String> arrayList = new ArrayList<>();
    5.     public static void main(String[] args) {
    6.         Prototype1 prototype1 = new Prototype1();
    7.         prototype1.setName("orign object");
    8.         prototype1.setValue("orign object");
    9.         Prototype1 clonePrototype1 = prototype1.clone();
    10.         clonePrototype1.setName("clone object");
    11.         /** 发现添加了执行了clone对象的setValue之后,也修改了prototype1中的arrayList中数据 */
    12.         clonePrototype1.setValue("clone object");
    13.         System.out.println(prototype1);
    14.         System.out.println(clonePrototype1);
    15.     }
    16.     /**
    17.      * 浅拷贝
    18.      * @return
    19.      */
    20.     @Override
    21.     protected Prototype1 clone() {
    22.         try {
    23.             return (Prototype1)super.clone();
    24.         } catch (CloneNotSupportedException e) {
    25.             e.printStackTrace();
    26.         }
    27.         return null;
    28.     }
    29.     /**
    30.      * 深拷贝
    31.      * @return
    32.      */
    33. //    @Override
    34. //    protected Prototype1 clone() {
    35. //        Prototype1 prototype1 = null;
    36. //        try {
    37. //            prototype1 = (Prototype1)super.clone();
    38. //            prototype1.setArrayList(new ArrayList<>());
    39. //        } catch (CloneNotSupportedException e) {
    40. //            e.printStackTrace();
    41. //        }
    42. //        return prototype1;
    43. //    }
    44.     public void setValue(String value) {
    45.         this.arrayList.add(value);
    46.     }
    47.     public List<String> getValue() {
    48.         return this.arrayList;
    49.     }
    50. }

    执行结果如下所示

    1. Prototype1(name=orign object, arrayList=[orign object, clone object])
    2. Prototype1(name=clone object, arrayList=[orign object, clone object])
    3. Process finished with exit code 0

    因为Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。

    今天的文章内容就这些了:

    写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。

    更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

  • 相关阅读:
    【VSCode】Windows环境下,VSCode 搭建 cmake 编译环境(通过配置文件配置)
    为什么账号关联对于卖家来说是非常可怕的
    小学生python游戏编程arcade----坦克大战3
    SAP UI5 Gateway Export 和 Client Export 的比较
    activiti 通过xml上传 直接部署模型
    厚膜功率电阻器制造:优化性能
    linux 网络命令
    新上线游戏产品需不需要防御?
    Fiber
    通过求解数学模型来选择编码节点的最佳数量和位置(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/qq_26470817/article/details/132976511