设计模式之原型模式

概念原文

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:不一样
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwx-apollo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值