创建模式之单例、原型(续)

      在上篇博文中我们已经简单的阐述了大部分有关单例(Singleton)模式的知识点,主要包括何谓单例、单例使用场景、单例几种实现方式及其特点以及单例的局限性。接下来我们将着重阐述有关原型(Prototype)的一些常识,主要涉及原型的用意、实现形式,以及与之相关的clone条件与equals方法和深浅拷贝等问题。

      所谓原型(Prototype)模式,是指通过给出一个原型对象来指明所要创建的对象类型,然后用复制这个原型对象的办法创建出更多同类型的对象。下图左侧是原型模式的一般性结构示意图,右侧是简单的实现样例。

      原型(Prototype)模式主要采用的是java的clone克隆,克隆有克隆的前提(即满足的条件),也有深、浅之别。

      首先,我们来看看克隆满足的条件:1、对任何的对象x,都有 x.clone() != x。即克隆对象与原对象不是同一个对象。2、对任何的对象x,都有 x.clone().getClass() == x.getClass(),即克隆对象与原对象的类型是一样。3、如果对象x的equals()方法定义恰当的话,那么 x.clone().equals(x)应当是成立的。 在java语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。(一般来说,clone前两个条件必须,后一个可选)。

      其次,我们来看看深浅克隆(即拷贝)的问题。浅克隆是指仅仅克隆所考虑的对象,而不克隆它所引用的对象,而深克隆是指把要克隆的对象及其所引用的对象都克隆一遍,这种对引用到的对象的克隆称之为间接克隆。(注:深克隆要深入到多少层是一个不易确定的问题)。

      最后,我们再共同关注下克隆满足条件之3equals()方法。关于此条件的满足,很多人误认为可以通过继承得到java.lang.Object对象的equals()方法就足够了,这其实是一个误区点。在java的源码中java.lang.Object的equals()方法是这样的:

public boolean equals(Object obj) {
    return (this == obj);
}

     也就是说,这仅仅是地址空间而非对象内容的比较,当两个变量同时指向一个对象时,equals()方法才会返回true。很显然,这并不是适合所有需要被克隆的对象的。

     一般而言,为了做到深克隆,所有对象都需要实现java.Serializable这个串行化接口。在这里,我们简单地提一下利用序列化的方法做深克隆。

    记得在《java与模式》一书中讲到:把对象写到流里的过程是串行化过程(java程序师圈里戏称冷冻或腌咸菜),把对象从流中读出来的并行化过程称解冻或回鲜过程。应当指出,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此,“腌成咸菜”的只是对象的一个拷贝,java咸菜还可以回鲜。实现过程的核心代码大致为:

//deeply clone
public Object clone(){
      ByteArrayOutputStream bo = new ByteArrayOutputStream();
      ObjectOutputStream oo = new ObjectOutputStream(bo);
      oo.writeObject(this);
      ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
     ObjectInputStream oi = new ObjectInputStream(bi);
     return oi.readObject();
}

   关于原型(Prototype)模式,姑且阐述至此!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值