用原型实例指向创建对象的种类,并通过拷贝这些原型创建新的对象。Prototype模式允许一个对象再创建另一个可定制的对象,根本无需知道任何如何创建的细节。工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。它主要面对的问题是,“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临剧烈的变化,但是它们却拥有比较稳定的一致接口。
原型模式最大的特点是克隆一个现有的对象。这个克隆的结果有两种。
1、 浅复制,
2、 深复制。
这里我们需要探讨浅复制与深复制的原理,这样可能更方便大家理解这个原型模式的使用。我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象而不需要提供专门的new()操作就可以快速完成对象的创建,这就是一种有效的,快速的创建一个新对象的方法。
【浅复制】被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
【深复制】被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制一遍。
对于浅复制与深复制简而言之:
浅复制: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
深复制: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
主要运用场合:
1、如果说我们的对象类型不是刚开始就能确定,而是这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆一个新的类型更容易。
2、有时候我们可能在实际的项目中需要一个对象在某种状态下的副本,这个前提很重要,这点怎么理解呢。比如说:有的时候我们需要对比一个对象经过处理后的状态和处理前的状态是否发生过改变,可能我们就需要在执行某段处理之前是否发生过改变,这时我们就需要在执行此段处理之前,克隆这个对象此时状态的副本,然后等执行后的状态进行相应的对比,这样的应用在项目中也是经常会出现的。
3、当我们在处理一些对象比较简单,并且对象之间的区别很小,可能只是固定的几个属性不同的时候,可能我们使用原型模式更合适。
演示案例
public class Prototype implements Cloneable,Serializable{ private static final long serialVersionUID = 10L; private String strName; private RefObject refObject; public String getStrName() { return strName; } public void setStrName(String strName) { this.strName = strName; } public RefObject getRefObject() { return refObject; } public void setRefObject(RefObject refObject) { this.refObject = refObject; } /** * 浅复制 * 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。 */ @Override protected Object clone() throws CloneNotSupportedException { Prototype prototype = (Prototype) super.clone(); return prototype; } /** * 深复制 * 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。 * @return * @throws IOException * @throws ClassNotFoundException */ protected Object deepClone() throws IOException, ClassNotFoundException { 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(); } /** * 类内部引用对象,实现Serializable接口 * @author Mahc * */ public class RefObject implements Serializable{ private static final long serialVersionUID = 101L; } }
原型模式测试用例。
public class TestPrototype { public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { Prototype prototype = new Prototype(); RefObject refObject = prototype.new RefObject(); prototype.setRefObject(refObject); prototype.setStrName("Hello World!"); System.out.println("使用浅复制方法进行创建对象"); Prototype pt01 = (Prototype) prototype.clone(); System.out.println("============================"); System.out.println("比较prototype和pt01的str的数值:"); System.out.println(prototype.getStrName()); System.out.println(pt01.getStrName()); System.out.println("/*******************/"); System.out.println("修改pt1对象中str的值后,比较pt和pt1的str的值:"); pt01.setStrName("你好,世界"); System.out.println(prototype.getStrName()); System.out.println(pt01.getStrName()); System.out.println("/*******************/"); System.out.println("比较prototype和pt01中temp对象的值"); System.out.println(prototype.getRefObject()); System.out.println(pt01.getRefObject()); System.out.println("============================"); System.out.println("使用深复制方法进行创建对象"); pt01=(Prototype)prototype.deepClone(); System.out.println(prototype.getRefObject()); System.out.println(pt01.getRefObject()); } }
【转载使用,请注明出处:http://blog.csdn.net/mahoking】
参考资料
1、http://luckykapok918.blog.163.com/blog/static/20586504320121145522355/
原文地址:http://blog.csdn.net/mahoking/article/details/40274199