设计模式之原型模式
在面向对象编程中,设计模式是一种通用的解决方案,用于解决软件设计过程中常见的问题。原型模式(
Prototype Pattern
)作为创建型设计模式的一员,旨在通过复制现有对象来创建新对象,而非通过常规的构造函数。这种模式不仅简化了对象的创建过程,而且在特定情况下还能显著提升性能。
🧐1. 概念
原型模式允许客户端复制一个已存在的对象,而不是通过常规的构造器创建一个新的实例。这种方法的主要优点在于,如果对象的创建成本很高(例如,初始化过程复杂、需要从数据库加载大量数据等),那么通过复制现有对象的方式可以有效减少资源消耗,提高系统的整体性能。
Prototype
(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。ConcretePrototype
(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。Client
(客户端类):通过调用clone()
方法来创建新的对象,并展示了原始对象与克隆对象之间的独立性。
🎯2. 原型模式的作用
- 简化对象创建:通过复制现有的对象,可以避免复杂的构造过程,尤其是当对象的初始化需要进行大量的计算或资源分配时。
- 提高性能:对于那些创建成本高得对象,使用原型模式可以显著减少内存消耗和处理时间。
- 增加系统灵活性:通过修改原型对象得属性,可以快速生成不同状态的新对象,这比通过继承来实现更加灵活。
📦3. 实现
实现原型模式的核心在于定义一个原型接口,该接口包含一个用于复制自身的克隆方法。在不同的编程语言中,实现方式可能会有所不同,但基本思路是一致的。
1. 定义原型接口
publicinterfacePrototypeextendsCloneable{Prototypeclone();}
此处的
Cloneable
接口是一个标记接口,表示该类可以被克隆。
类似的标记接口还有
Serializable
:用于标记一个类的对象可以被序列化和反序列化。RandomAccess
:用于标记一个列表支持随机访问,即通过索引直接访问元素吗,而不是遍历。Remote
:用于远程方法调用,标记一个类支持远程方法调用。
2. 定义具体的原型类
publicclassConcretePrototypeimplementsPrototype{privateString attribute;publicConcretePrototype(String attribute){this.attribute = attribute;}@OverridepublicPrototypeclone(){try{return(ConcretePrototype)super.clone();}catch(CloneNotSupportedException e){thrownewAssertionError("Cannot clone.", e);}}publicStringgetAttribute(){return attribute;}publicvoidsetAttribute(String attribute){this.attribute = attribute;}}
3. 定义客户端
publicclassClient{publicstaticvoidmain(String[] args){ConcretePrototype prototype =newConcretePrototype("Initial Value");ConcretePrototype clonedPrototype =(ConcretePrototype) prototype.clone();System.out.println("Original Attribute: "+ prototype.getAttribute());System.out.println("Cloned Attribute: "+ clonedPrototype.getAttribute());
clonedPrototype.setAttribute("Modified Value");System.out.println("After Modification:");System.out.println("Original Attribute: "+ prototype.getAttribute());System.out.println("Cloned Attribute: "+ clonedPrototype.getAttribute());}}
4. 结果
在这个示例中,
ConcretePrototype
类实现了
Prototype
接口,并提供了具体的
clone()
方法实现。客户端代码展示了如何通过调用
clone()
方法来创建新的对象,并展示了原始对象与克隆对象之间的独立性。
📰 4. 应用场景
- 对象创建成本高:当对象的创建对象过程非常复杂或耗时,例如需要从网络加载数据、执行复炸的算法等,使用原型模式可以通过复制现有对象来节省时间和资源。
- 避免复杂的构造过程:如果对象的创建涉及到复杂的初始化步骤,使用原型模式可以简化这些步骤,通过复制已有对象来快速生成新的对象。
- 动态对象创建:在某些情况下,程序需要根据用户的输入或其他条件动态地创建对象。原型模式提供了一种灵活的方式来满足这种需求,无需预先定义所有的对象类型。
- 实际项目当中使用原型模式,实现
Cloneable
接口并重写clone()
方法。或者编写自己的特有的原型类Prototype
,然后实现Prototype
的clone()
方法。
🔍5. 深拷贝和浅拷贝
在讨论原型模式时,深拷贝和浅拷贝是一个不可忽视的话题。浅拷贝只会复制对象的基本数据类型和其他对象的引用,而不会递归地复制引用对象本身。相反,深拷贝会递归地复制整个对象树,确保新对象与原有对象完全独立。
在
Java
中, 默认的
clone()
方法实现的是浅拷贝。如果需要实现深拷贝,通常需要手动编写代码来处理对象中的引用类型属性。例如,可以使用序列化和反序列化的方式来实现深拷贝:
publicclassDeepClonePrototypeimplementsCloneable,Serializable{privatetransientString attribute;// 使用 transient 修饰符表示不参与序列化publicDeepClonePrototype(String attribute){this.attribute = attribute;}publicStringgetAttribute(){returnthis.attribute;}publicvoidsetAttribute(String attribute){this.attribute = attribute;}@OverrideprotectedDeepClonePrototypeclone(){try{// 使用序列化和反序列化实现深拷贝ByteArrayOutputStream byteOut =newByteArrayOutputStream();ObjectOutputStream out =newObjectOutputStream(byteOut);
out.writeObject(this);ByteArrayInputStream byteIn =newByteArrayInputStream(byteOut.toByteArray());ObjectInputStream in =newObjectInputStream(byteIn);return(DeepClonePrototype) in.readObject();}catch(IOException|ClassNotFoundException e){thrownewAssertionError("Cannot clone.", e);}}}
版权归原作者 JAVA开发区 所有, 如有侵权,请联系我们删除。