java与模式孙悟空_设计模式之原型模式 - chenxkang的个人空间 - OSCHINA - 中文开源技术交流社区...

原型模式是一种创建型设计模式,它允许一个对象再创建另一个可定制的对象,根本无需知道任何创建的细节。

定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

问题描述:创建一个重复的结构复杂的对象时的成本比较大,比如细胞分裂、新建一个模板等。

解决方案:将这个结构复杂的对象作为一个原型,然后通过复制这个原型对象来创建更多同类型的对象。

结构图:

18d0c7d26535d45310503efefa279a9e.png

说明:

(1)抽象原型类(Cloneable):这是一个抽象角色,可用接口或抽象类来实现,这里声明了一个克隆的方法,是所有具体原型类共同拥有的父类或接口;

(2)具体原型类:继承或实现抽象原型类的克隆方法,返回自己的一个克隆对象;

(3)使用者(User):让一个已有的原型对象通过调用其克隆方法,获得该对象的克隆对象。

举个栗子:讲一个孙悟空拔毛变小猴儿的故事,将孙悟空作为一个原型对象,克隆出不同的小猴儿,使用原型模式来实现。

1. 新建一个原型类MonkeyPrototype,实现Cloneable接口中的clone()方法,返回自己的一个克隆对象,其中引用了Address对象。代码如下:

e24ee599d1c2c9badd0f3a56d2e0c9e1.png

b18157b0154b86403cfa73152458d78b.png

2. 在类PrototypeFragment中使用一个已有的原型对象,通过调用其克隆方法获得该对象的克隆对象,并对克隆对象的名字name和地址address进行更改。代码如下:

c6412209786fd3e0014b34da47e2fb15.png

4. 运行后的效果,如图所示:

c18204bfe619b162bb7ad77f9cd71d97.png

上面的实现方式叫作浅克隆,它只能克隆对象本身,对于依附于对象的对象则不予克隆,只对其地址克隆。栗子中,Address就是依附于原型类MonkeyPrototype的对象的对象,只克隆了它的引用地址,当克隆对象monkey_A对地址做出改动时,比如将“花果山”改为“峨眉山”,原型对象和克隆对象的地址都发生了改变。也就是说,如果原型对象的成员变量是值类型,则进行复制,不会互相影响;如果是引用类型,比如Address,则将其地址复制,实质上指向的是同一个对象。

浅克隆需要注意的地方:

(1)被克隆的对象需要实现需要实现Cloneable;

(2)要重写clone() 方法;

(3)对于依附于被克隆对象的对象,只克隆其地址。一旦更改都会改变。

下面用深克隆来实现原型模式。具体实现方式如下:

1. 让原型类MonkeyPrototype实现可序列化接口Serializable,增加一个deepClone()方法。代码如下:

b518f49dc0f65653cea40f5cd67a7a8c.png

2. 在类PrototypeFragment中仍然使用这个已有的原型对象,通过调用deepClone()方法对该对象的进行深克隆,并对克隆对象的名字name和地址address进行更改。代码如下:

be43ea31fe60da47d50abf4b2fdbd8b5.png

3. 运行后的效果,如图所示:

56308362433b662aa3fe31a89f376ee4.png

由上可知,深克隆利用了IO流进行存储,然后进行读取,不仅对克隆对象进行克隆,而且对其依附着的对象也进行了克隆。如栗子所示,原型猴儿携带的信息包含孙悟空、六耳猕猴和峨眉山,深克隆后的对象是猴儿B,我更改了名字和地址,其中名字name是值类型成员变量,则复制后改变不会影响原型对象的值,地址address是引用类型成员变量,因为是深克隆,所以也复制了一份给克隆对象,所以更改后也将不会影响到原型对象中的地址值。

深克隆,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象。

深克隆需要注意的地方:

(1)利用IO流进行存储,然后进行读取;

(2)需要实现可序列化接口Serializable。

优点:

(1)当创建一个结构复杂的对象时,原型模式可以简化其创建过程,通过复制已有的实例来获得相同的对象;

(2)简化创建结构,不需要专门的工厂存在,仅需要实现克隆方法即可。

缺点:

(1)必须实现Cloneable接口;

(2)逃避构造函数的约束;

(3)克隆方法在类的内部,加重类的职责,当需要对已有类进行改造时需要修改原型类。

使用场景:

(1)当创建成本比较大的时候,新的对象可以使用原型模式来获得;

(2)系统要保存对象的状态,并且对象本身占用内存很少,比如要恢复到某个时间的某种状态,可以使用原型模式配合备忘录模式来实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值