【却说那妖精与大圣斗经半日,不分胜败。行者把棒丢起,叫一声“变!”就以一变十,以十变百,以百变千,半天里,好似蛇游蟒搅,乱打妖邪。妖邪慌了手脚,将身一闪,化道清风,即奔碧空之上逃走。行者念声咒语,将铁棒收做一根,纵祥光一直赶来。】
在西游记第九十五回【假合真形擒玉兔 真阴归正会灵元】中,孙行者“殴打”玉兔精的时候,将如意金箍棒从一根化作了千百根,打得玉兔精无从招架。
这千百根金箍棒的属性应该是一样的,如果孙悟空每次都要新建一个新的金箍棒对象,然后把原有的金箍棒的属性复制过去,如此重复千百次,未免太过麻烦,所以我们这里假设孙悟空使用了原型模式来创建多个相同属性的金箍棒实例。
在详细介绍原型模式之前,我们需要先了解一下java.lang.Object#clone()方法以及java.lang.Cloneable接口的功能及实现:
java.lang.Cloneable
/**
* A class implements the <code>Cloneable</code> interface to
* indicate to the {@link java.lang.Object#clone()} method that it
* is legal for that method to make a
* field-for-field copy of instances of that class.
* <p>
* Invoking Object's clone method on an instance that does not implement the
* <code>Cloneable</code> interface results in the exception
* <code>CloneNotSupportedException</code> being thrown.
* <p>
* By convention, classes that implement this interface should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* <p>
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
*
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
Java doc的意思大致是说:一个类实现了Cloneable接口,就是在运行时向虚拟机表明当前类可以合法地使用Object类的clone()方法,来进行对象内容的拷贝。假设没有实现Cloneable接口就调用clone()方法的话,虽然能够通过编译,但是会在运行时抛出java.lang.CloneNotSupportedException。一般来说,实现Cloneable接口的类需要重写Object类的protected方法,并且声明重写方法为public的。需要注意的是,Cloneable接口并不包含clone()方法。因此,一个类仅仅实现Cloneable接口就想成功实现clone()功能是不可能的。即使反射调用也不保证会成功。
也就是说,要想调用源生的Object类的clone()方法,我们必须让原型类实现Cloneable接口。那么,Object类的clone()的优势在哪里呢?
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object