设计模式之原型模式

Posted lwx-apollo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之原型模式相关的知识,希望对你有一定的参考价值。

概念原文

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.

概念翻译

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

特点

  • 性能优良:Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  • 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

优点与缺点

优点

  • 性能提高
  • 逃避构造函数的约束。

缺点

  • 需要为每一个类都配置一个 clone 方法
  • clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
  • 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

应用场景

  • 资源优化场景
  • 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等
  • 性能和安全要求的场景
  • 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
  • 一个对象多个修改者的场景
  • 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用

项目或框架应用

  • java中的Object中的clone方法

代码实现

实现代码

/**
 * The class used to be a prototype for students' scores .
 * Implements Cloneable interface and override clone method to clone prototype .
 * These properties set default value to check whether the value of properties can be cloned when the object is cloned .
 * @author luowenxing
 */
public class StudentScore implements Cloneable 

    private int math = 100;

    private int chinese = 100;

    private int english = 100;

    private String name;

    public void score() 
        System.out.println(name + "'s score are as follows : math-" + math + " ,chinese-" + chinese + " ,english-" + english + " .");
    

    @Override
    protected StudentScore clone() throws CloneNotSupportedException 
        System.out.println("Invoke clone .");
        return (StudentScore) super.clone();
    

    public void setMath(int math) 
        this.math = math;
    

    public void setChinese(int chinese) 
        this.chinese = chinese;
    

    public void setEnglish(int english) 
        this.english = english;
    

    public void setName(String name) 
        this.name = name;
    

测试

public class PrototypeTest 
    public static void main(String[] args) throws CloneNotSupportedException 
        StudentScore jay = new StudentScore();
        jay.setName("Jay");
        jay.setChinese(95);
        jay.setEnglish(85);
        jay.setMath(100);
        jay.score();
        // clone object
        StudentScore tom = jay.clone();
        // clone object does not equals source object
        System.out.println(jay.equals(tom));
        // reset student's name, and does not set score
        tom.setName("Tom");
        tom.score();
    

测试结果

可以看出原型模式clone出的对象是不一样的,会重新申明一块内存空间,但是属性内容是一样的。

知识拓展

  • Java 自带的原型模式基于内存二进制流的复制,不会调用构造函数。
  • 浅拷贝和深拷贝:
    浅拷贝:Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝,其他的原始类型比如int、long、char、string(当做是原始类型)等都会被拷贝。
    注意: 使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个原始类型或不可变对象。
    深拷贝:对私有的类变量进行独立的拷贝
    如:thing.arrayList = (ArrayList)this.arrayList.clone();

相关面试题

  1. Q:什么是原型模式?
    A:见上述文章
  2. Q:原型模式的特点
    A:见上述文章
  3. Q:原型模式中的clone的对象内存地址分配一样吗?
    A:不一样

以上是关于设计模式之原型模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之原型模式

C#设计模式之五原型模式(Prototype Pattern)创建型

js面向对象程序设计之构造函数

设计模式之-创建模式-原型模式

《设计模式之禅》之原型模式

设计模式之原型模式