一文带你理解原型模式

原型模式是通过已有的模板来客隆对象的一种创建型设计模式。原型就是一种模板。主要适用于通过new关键字来创建对象比较复杂时的场景。

定义

用原型模板指定创建对象的种类,并通过拷贝这些原型对象创建新的对象。

场景

  1. 当一个对象的构造,利用new和通过clone的效率差别很大时,可以考虑使用原型模式。特别是在循环体内部,效率的提升会更加明显。
  2. 当需要对原始实例进行写保护的时候,可以通过克隆一份副本实例提供给使用者。

特点

  1. 降低创建某些对象的资源消耗
  2. 对象克隆中保护性拷贝和非保护性拷贝
  3. 通过Cloneable接口创建对象时,不会执行类的构造方法

保护性拷贝(深拷贝)

在对象的拷贝时,针对引用类型不是直接通过引用指向来实现,而是遍历引用类型,对引用类型再执行clone方法,也可以理解为对于引用类型,会重新创建新的实例。

保护性拷贝需要确保的是,修改拷贝对象的所有结构,对原型实例不会产生任何影响

非保护性拷贝(浅拷贝)

在对象的拷贝时,只是通过对象的clone方法生成副本对象,如果原型对象有引用类型的变量,在副本对象中修改引用类型变量,也会对原型变量造成影响。这很好理解,因为原型对象和副本对象的引用都指向了同一块内存空间。

非保护性拷贝需要注意的是,在原型对象中有引用类型的变量时,需要确定副本实例在系统中是否对原型实例构成了威胁

源码分析

下面是一份重写Object类的````clone``方法实现的原型模式代码

public class PrototypeUser {

  private String name;
  private int age;
  private Address address;

  @Override protected Object clone() throws CloneNotSupportedException {
    PrototypeUser clone = (PrototypeUser) super.clone();
    clone.address = (Address) address.clone();
    return clone;
  }

  public static class Address {
     private String cuty;
     private String street;
     
    @Override protected Object clone() throws CloneNotSupportedException {
      return super.clone();
    }
  }
}

以上代码中可以看出,针对基础数据类型ageString类型的克隆,是直接调用了Object类的克隆方法,而针对引用类型的变量address则调用了address自身的克隆方法。这样做就实现了保护性拷贝的操作。

当然并不是所有的原型模式都依赖Objectclone方法。

原型模式主要解决的是创建复杂对象的问题。看以下代码片段

public class Prototy {

  private String name;

  private List<String> todos = new ArrayList<>();

  public Prototy copy() {
    Prototy p = new Prototy();
    p.name = name;
    p.todos = new ArrayList<>();
    if (todos.size() > 0) {
      p.todos.addAll(todos);
    }
    return p;
  }
}

上述代码片段中的copy方法,也是利用了原始的对象生成内部构造相同的新对象。

这样做简化了对象创建流程,隐藏了变量赋值过程,而且copy生成的对象与原型对象是完全独立的。不存在浅拷贝引发的问题。在特定环境下,可以用copy出的对象代替原始对象,这样子对原始对象的数据还可以进行隐藏保护,不会被随意篡改。

总结

原型模式本质上是对象的拷贝,在这里面需要注意深拷贝和浅拷贝造成的不同影响。原型模式的主要用途是削减复杂对象创建过程的资源消耗;还有就是对实例的数据保护,通过生成副本对象,来对原始对象的数据进行写保护。
原型模式的最大优点就是更加节省的创建对象,特别是在循环体内部,这种优化是很高效的。当然在利用Objectclone方法克隆对象时,不会执行类的构造方法,这也是需要注意的,特别是类在构造器中进行了一些重要的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值