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

原型模式

工厂方法中生成对象,都是经过类似流水线操作的方式对每一个对象进行构造函数调用,可是每个成品却都是十分相似。当然这里是举例结构较为简单的对象工厂。那么,如果能够直接对对象进行复制而生成相似对象,就能省去将产品放到流水线的工序和其他杂七杂八的辅助工序(赋默认值、赋初始值…)从而提高创建对象的效率。这就是原型模式的由来。

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

使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

参与角色:① 抽象原型 ② 具体原型
在这里插入图片描述
客户端在编程时是基于抽象Prototype,按需选择适合的原型实现类,这样能够使系统具备较好的扩展性。

代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
深克隆和浅克隆

根据复制原型对象的同时是否复制包含在原型对象引用类型的成员变量,原型模式的克隆机制可分为深克隆和浅克隆。

浅克隆
值类型成员变量(byte,int,short…)会复制一份到新对象。
引用类型成员变量(对象),会复制地址到新对象,即旧对象和克隆对象的引用成员变量都是指向同一个对象地址。

深克隆
值类型变量和引用类型变量都会复制一份到克隆对象中,旧对象和克隆对象的引用成员变量不再指向同一个对象地址。

浅克隆较为简便的实现方式

java语言给我们提供了Object.clone()和Cloneable接口。可以利用这种方式实现原型复制,不过被克隆对象需要实现Cloneable接口已达到标识作用,否则会报CloneNoSupportedException。
在这里插入图片描述
正确的编写方式是原型类需要Cloneable接口,在克隆方法里调用Object的clone方法。

这里还有个点,也就是使用clone()要达到深克隆效果是比较麻烦的,也是我为什么说这种方式比较适合实现浅克隆。举个例子。
在这里插入图片描述
这里的Ref只是用于实验,没有实体内容。
在这里插入图片描述
运行结果:
在这里插入图片描述
也就是说就算Ref类实现了Cloneable接口,然后ConcretePrototype3想进行深克隆,则Ref类也必须有一个方法调用Object的clone方法。接着在ConcretePrototype3类的克隆方法里调用它获取Ref的克隆对象,再将Ref的克隆对象set到ConcretePrototype3的克隆对象的对应成员变量里。十分麻烦。

深克隆较为简便的实现方式

利用序列化。通过序列化方式不仅可以复制原型本身,也可以复制它的引用成员变量,但要注意的点是,可序列化的类必须实现Serializable接口。
在这里插入图片描述
在这里插入图片描述
最后结果:
在这里插入图片描述
从输出中,可以看出,这种方式不仅能实现原型对象的克隆也能对其引用对象进行克隆。
使用序列化方式将对象序列化后写入流中,再从流中反序列化得到包含引用对象的克隆对象。因而可以采用这种方式达到对象深克隆的效果。

原型管理器

原型管理器是一个原型对象的克隆工厂,即由它来维护克隆对象。
在这里插入图片描述
下面是原型管理器的代码:
在这里插入图片描述
既然是管理器,那肯定需要维护它的唯一,所以这里是采用了单例模式结合原型模式而实现的一个原型管理器。采用静态内部类实现单例模式是由于其采用懒加载的方式,在首次使用时才会对其静态进行初始化,因而能够保证线程安全。

原型模式适用场景:

  1. 创建对象的成本较大,可以采用复制已有对象来获取相似新对象。
  2. 系统需要保存对象状态,可以对状态进行一个克隆。
  3. 需要避免使用分层次的工厂类来创建分层次的对象,并且对象只有一个或者很少的几个组合状态,那么采用原型模式会更加方便。(注:组合状态可数,则可以根据多种状态复制出相应的对象

优点:

  1. 可以提高创建复杂对象的效率。
  2. 对抽象进行编程,扩展性较好。
  3. 相对于工厂方法,原型模式缩减了工厂类这一部分代码,系统的类数量可以有效减少。
  4. 可辅助实现撤销操作,对某个状态的对象进行赋值并保存。

缺点:

  1. 克隆方法位于类的内部,当对现有原型类进行改造时,需要修改源代码,违背了开闭原则。
  2. 当对象之间存在复杂的多重引用时,为了实现深克隆,需要让每一层的引用对象都支持深克隆,实现会较为复杂。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值