一、说说鸣人的影分身
话说鸣人听了水木老师的建议偷出了卷轴并且学会了一招禁术:影分身之术。当鸣人使用影分身之术的时候就会有好多个和鸣人一模一样的人出现,就像复制出来的一样,这种影分身之术在面向对象的设计领域里就叫做原型模式。
二、什么是原型模式
有了上边的鸣人的例子,我们再理解圆形模式的定义应该会更简单了,GOF给它的定义是:用原型实例指定创建对象的种类并且通过拷贝这些原型对象创建新的对象。
在Java中提供了clone()方法来实现对象的克隆,所以原型模式(Prototype)实现变得简单的多了。
三、再来说说clone()方法
Java的所有类 都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制:
protected Object clone()
子类也可以将这个方法覆盖掉,用自己的逻辑实现自己的复制方法。可以被使用clone()方法的类都必须实现Cloneable接口,Cloneable接口只起一个作用就是在运行时期通知Java虚拟机可以安全地在这个类上使用clone方法。
克隆又分为两种:浅克隆和深度克隆
浅度克隆:
如上图所示,浅度复制只是复制对象的值,我们知道对象的属性一共分为两种,基本类型和引用类型,对于浅度复制基本类型的数据会复制一份到新的对象中去,对于引用类型的属性仅仅复制引用的值,引用所指向的具体的对象不会复制,所以A和B实际上是用的同一个对象c,如果再A中改变c的属性,B中也能看到,因为改变的是两者共有对象。Java提供的clone方法就是这种类型的。
深度复制与浅度复制的不同就是深度复制不但会复制对象的引用,并且还会复制引用所指的对象。所以在第二幅图中A和B是指向的不同的对象,此时在A中操作c对象不会对B产生任何影响。
克隆满足的条件:
1、对任何对象x,都有:x.clone()!=x.换言之,克隆对象与原来的对象不是同一个对象。
2、对任何对象x,都有:x.clone().getClass==x.getClass(),换言之,克隆对象与原对象的类型一致。
3、如果对象x的equals()方法定义恰当的话,那么x.clone().equals(x)应该是成立的。
关于equals方法的说明:被克隆的对象按照他们的内部状态是否可变,划分为可变对象和不可变对象(String的内部数值是不能改变的)。对于可变对象只有当他们是同一个对象时才会返回true,而对于不变对象,当他们的内部状态值是一样的时候就认为是true,但是内部状态一直的不一定就是同一个对象。
四、原型模式的结构
原型模式模式分为两种,一种是不带管理类的原型模式,另一种是带管理类的原型模式。
下面这种是不带管理类的原型