【设计模式】【创建型模式(Creational Patterns)】之原型模式(Prototype Pattern)

发布于:2024-11-29 ⋅ 阅读:(29) ⋅ 点赞:(0)

1. 设计模式原理说明

原型模式(Prototype Pattern) 是一种创建型设计模式,它允许你通过复制现有对象来创建新对象,而无需通过构造函数来创建。这种方式可以提高性能,尤其是在对象初始化需要消耗大量资源或耗时较长的情况下。原型模式的关键在于对象的克隆方法,通过该方法可以创建一个与原对象具有相同属性的新对象。

主要角色
  1. Prototype(抽象原型类):声明了克隆自身的接口。
  2. ConcretePrototype(具体原型类):实现了克隆方法,用于创建新的对象实例。
  3. Client(客户端):使用原型类创建新对象。

2. UML 类图及解释

UML 类图
+----------------+                +---------------------+
|   Prototype    |                | ConcretePrototype   |
|----------------|                |---------------------|
| + clone(): Prototype            | + clone(): Prototype|
+----------------+                +---------------------+
                                           
+----------------+                         |
|   Client       |                         |
|----------------|                         |
| - prototype: Prototype                  |
|                                +---------+
| + createClone(): Prototype               |
| + mainMethod(): void                     |
+----------------+                         |
类图解释
  • Prototype:定义了一个克隆自身的接口。这个接口通常是一个 clone 方法,用于创建一个新的对象实例。
  • ConcretePrototype:实现了 Prototype 接口中定义的 clone 方法,用于创建新的对象实例。具体的克隆逻辑由具体原型类实现。
  • Client:使用原型类创建新对象。客户端持有一个原型对象的引用,并通过调用其 clone 方法来创建新的对象实例。

3. 代码案例及逻辑详解

Java 代码案例
// 抽象原型类
interface Prototype {
    Prototype clone();
}

// 具体原型类
class ConcretePrototype implements Prototype {
    private String value;

    public ConcretePrototype(String value) {
        this.value = value;
    }

    @Override
    public Prototype clone() {
        // 浅拷贝
        return new ConcretePrototype(this.value);
    }

    @Override
    public String toString() {
        return "ConcretePrototype [value=" + value + "]";
    }
}

// 客户端
class Client {
    private Prototype prototype;

    public Client(Prototype prototype) {
        this.prototype = prototype;
    }

    public Prototype createClone() {
        return prototype.clone();
    }

    public static void main(String[] args) {
        ConcretePrototype original = new ConcretePrototype("Original Value");
        Client client = new Client(original);

        ConcretePrototype clone1 = (ConcretePrototype) client.createClone();
        ConcretePrototype clone2 = (ConcretePrototype) client.createClone();

        System.out.println("Original: " + original);
        System.out.println("Clone 1: " + clone1);
        System.out.println("Clone 2: " + clone2);
    }
}
C++ 代码案例
#include <iostream>
#include <string>

// 抽象原型类
class Prototype {
public:
    virtual Prototype* clone() const = 0;
    virtual ~Prototype() {}
};

// 具体原型类
class ConcretePrototype : public Prototype {
private:
    std::string value;

public:
    ConcretePrototype(const std::string& value) : value(value) {}

    Prototype* clone() const override {
        return new ConcretePrototype(*this);
    }

    friend std::ostream& operator<<(std::ostream& os, const ConcretePrototype& p) {
        return os << "ConcretePrototype [value=" << p.value << "]";
    }
};

// 客户端
class Client {
private:
    Prototype* prototype;

public:
    Client(Prototype* prototype) : prototype(prototype) {}

    Prototype* createClone() {
        return prototype->clone();
    }

    ~Client() {
        delete prototype;
    }
};

int main() {
    ConcretePrototype original("Original Value");
    Client client(&original);

    ConcretePrototype* clone1 = dynamic_cast<ConcretePrototype*>(client.createClone());
    ConcretePrototype* clone2 = dynamic_cast<ConcretePrototype*>(client.createClone());

    std::cout << "Original: " << original << std::endl;
    std::cout << "Clone 1: " << *clone1 << std::endl;
    std::cout << "Clone 2: " << *clone2 << std::endl;

    delete clone1;
    delete clone2;

    return 0;
}
Python 代码案例
import copy

# 抽象原型类
class Prototype:
    def clone(self):
        pass

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

    def clone(self):
        # 使用深拷贝
        return copy.deepcopy(self)

    def __str__(self):
        return f"ConcretePrototype [value={self.value}]"

# 客户端
class Client:
    def __init__(self, prototype):
        self.prototype = prototype

    def create_clone(self):
        return self.prototype.clone()

if __name__ == "__main__":
    original = ConcretePrototype("Original Value")
    client = Client(original)

    clone1 = client.create_clone()
    clone2 = client.create_clone()

    print("Original:", original)
    print("Clone 1:", clone1)
    print("Clone 2:", clone2)
Go 代码案例
package main

import (
    "fmt"
)

// 抽象原型类
type Prototype interface {
    Clone() Prototype
}

// 具体原型类
type ConcretePrototype struct {
    Value string
}

func (p *ConcretePrototype) Clone() Prototype {
    // 浅拷贝
    return &ConcretePrototype{Value: p.Value}
}

func (p *ConcretePrototype) String() string {
    return fmt.Sprintf("ConcretePrototype [value=%s]", p.Value)
}

// 客户端
type Client struct {
    prototype Prototype
}

func NewClient(prototype Prototype) *Client {
    return &Client{prototype: prototype}
}

func (c *Client) CreateClone() Prototype {
    return c.prototype.Clone()
}

func main() {
    original := &ConcretePrototype{Value: "Original Value"}
    client := NewClient(original)

    clone1 := client.CreateClone().(*ConcretePrototype)
    clone2 := client.CreateClone().(*ConcretePrototype)

    fmt.Println("Original:", original)
    fmt.Println("Clone 1:", clone1)
    fmt.Println("Clone 2:", clone2)
}

4. 总结

原型模式 是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过构造函数。这种方式可以提高性能,特别是在对象初始化需要消耗大量资源或耗时较长的情况下。原型模式的主要优点包括:

  1. 性能提升:通过复制现有对象来创建新对象,可以避免复杂的初始化过程,提高性能。
  2. 代码简洁:减少了重复的代码,特别是当对象的初始化过程非常复杂时。
  3. 灵活度高:可以通过修改原型对象的属性来创建不同配置的对象实例。

然而,原型模式也有一些缺点,例如:

  1. 深拷贝和浅拷贝的问题:需要仔细处理对象的深拷贝和浅拷贝问题,否则可能会导致意外的行为。
  2. 类必须实现克隆方法:每个需要被克隆的类都必须实现 clone 方法,这可能会增加代码的复杂性。

总的来说,原型模式在需要频繁创建相似对象的场景中非常有用,但在简单对象的创建中可能显得过于复杂。选择是否使用原型模式应根据具体的需求和场景来决定。