设计模式- 原型模式(Prototype Pattern)结构|原理|优缺点|场景|示例

目录

设计模式(分类) 设计模式(六大原则)

创建型

工厂方法 抽象工厂模式 单例模式 建造者模式 原型模式

结构型

适配器模式

原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过复制现有的对象(即原型)来创建新对象,而不是每次都通过new操作符来创建对象。这种模式适用于创建新对象的成本较大(如初始化耗时、占用资源较多)或者创建过程较复杂的场景,通过克隆原型对象可以快速、便捷地生成相似或相同状态的新对象。

模式结构

原型模式通常包含以下角色:

  1. 原型(Prototype) :定义一个克隆自身的接口,通常包含一个clone()方法。
  2. 具体原型(Concrete Prototype):实现原型接口,提供克隆自身的具体实现。具体原型类需要能够复制自身的状态,并可能包含必要的辅助方法来支持复制过程。

工作原理

  • 客户端 :通过调用具体原型对象的clone()方法来创建新对象,无需关心对象的内部构造细节。
  • 具体原型 :实现clone()方法,负责复制自身的状态,并可能需要处理深层次对象的递归复制。新创建的对象与原对象状态相同,但具有独立的标识(即不同的内存地址)。

优缺点

优点
  • 简化对象创建过程:对于复杂的对象,使用原型模式可以简化对象的创建过程,避免重复初始化或执行耗时的操作。
  • 提高性能:通过复制现有对象创建新对象,特别是在对象初始化成本较高的情况下,可以显著提高性能。
  • 支持动态增加或修改产品类:如果产品类需要动态添加或修改,使用原型模式可以避免对客户端代码产生影响。
缺点
  • 对象必须支持克隆:不是所有的对象都能很容易地实现克隆,尤其是包含复杂状态或引用其他对象时,克隆实现可能变得复杂。
  • 深拷贝与浅拷贝问题:在复制包含其他对象引用的状态时,需要考虑是否需要深度复制这些引用对象,否则可能导致数据不一致或意外共享状态。

适用场景

  • 对象创建成本较高:当创建新对象需要消耗大量资源、执行复杂操作或初始化时间较长时,使用原型模式可以有效提高效率。
  • 需要动态创建相似或相同状态的对象:如游戏中的角色复制、文档模板应用、数据恢复场景等,通过克隆原型对象快速生成新对象。
  • 需要避免对象之间的相互依赖:通过复制已有对象来创建新对象,可以减少对象间的依赖关系,降低系统的耦合度。

代码示例(以Java为例)

在Java中实现原型模式,可以利用Java内建的Cloneable接口和Object类提供的clone()方法。下面是一个简单的Java代码示例:

java 复制代码
// 原型接口(由于Java中没有显式的原型接口,此处省略)

// 具体原型类实现Cloneable接口以支持克隆
public class ConcretePrototype implements Cloneable {
    private String attr1;
    private String attr2;

    public ConcretePrototype(String attr1, String attr2) {
        this.attr1 = attr1;
        this.attr2 = attr2;
    }

    // 提供公共的clone方法
    @Override
    public ConcretePrototype clone() throws CloneNotSupportedException {
        return (ConcretePrototype) super.clone();
    }

    // 其他方法、属性...

    public String getAttr1() {
        return attr1;
    }

    public String getAttr2() {
        return attr2;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        try {
            ConcretePrototype prototype = new ConcretePrototype("value1", "value2");
            ConcretePrototype clonedObject = prototype.clone();

            System.out.println(clonedObject.getAttr1());  // 输出:value1
            System.out.println(clonedObject.getAttr2());  // 输出:value2
        } catch (CloneNotSupportedException e) {
            // 不应该发生,因为ConcretePrototype实现了Cloneable接口
            e.printStackTrace();
        }
    }
}

在这个Java示例中:

  • ConcretePrototype类实现了Cloneable接口,表明它可以被克隆。
  • 重写了Object类的clone()方法,并将其声明为public,以便客户端可以直接调用。注意,虽然Cloneable接口没有实际的方法定义,但它是一个标记接口,用于指示对象支持克隆操作。
  • clone()方法中,调用super.clone()来执行实际的克隆过程。这会创建一个浅拷贝,即原始对象和克隆对象共享不可变的基本类型和对象引用。如果类中包含复杂对象或可变集合,可能需要在clone()方法中进行深度拷贝,以确保新对象的独立性。
  • 客户端代码通过调用prototype.clone()来创建新对象,捕获可能出现的CloneNotSupportedException异常(尽管在正确实现Cloneable的情况下,此异常通常不会抛出)。

请注意,Java的clone()方法默认执行的是浅拷贝,如果对象内部包含可变的复杂对象或集合,需要在clone()方法中手动进行深拷贝,以确保新对象的状态完整独立。例如,如果ConcretePrototype类中有一个可变的列表成员变量,需要在clone()方法中对其进行单独复制:

java 复制代码
private List<String> items;

// ...其他代码...

@Override
public ConcretePrototype clone() throws CloneNotSupportedException {
    ConcretePrototype clone = (ConcretePrototype) super.clone();
    clone.items = new ArrayList<>(this.items);  // 深拷贝列表
    return clone;
}

代码示例(以Python为例)

python 复制代码
import copy

# 原型接口
class Prototype:
    def clone(self):
        raise NotImplementedError("Subclasses must implement this method")

# 具体原型
class ConcretePrototype(Prototype):
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

    def clone(self):
        return copy.deepcopy(self)

# 客户端代码
def main():
    prototype = ConcretePrototype("value1", "value2")
    cloned_object = prototype.clone()
    print(cloned_object.attr1, cloned_object.attr2)  # 输出:value1 value2

if __name__ == "__main__":
    main()

在这个Python示例中:

  • Prototype类作为原型接口,定义了clone()方法,要求子类必须实现。
  • ConcretePrototype类继承自Prototype,实现了具体的clone()方法。这里使用copy.deepcopy()来实现深度克隆,确保新创建的对象与原对象状态相同且具有独立的标识。
  • 客户端代码通过调用ConcretePrototype对象的clone()方法来创建新对象,无需关心对象的内部构造细节。新创建的对象与原对象状态相同,但具有独立的标识。
相关推荐
杨充9 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充9 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充9 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充9 小时前
2.面向对象的特性
设计模式
杨充9 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充9 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充9 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯12 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯21 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式