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

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

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式     责任链模式     命令模式    备忘录模式          状态模式         访问者模式        中介者模式 


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

模式结构

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

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

工作原理

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

优缺点

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

适用场景

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

代码示例(以Java为例)

在Java中实现原型模式,可以利用Java内建的Cloneable接口和Object类提供的clone()方法。下面是一个简单的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()方法中对其进行单独复制:

private List<String> items;

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

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

代码示例(以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()方法来创建新对象,无需关心对象的内部构造细节。新创建的对象与原对象状态相同,但具有独立的标识。
  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值