原型模式(Prototype Pattern)和建造者模式(Builder Pattern)虽然都是创建型设计模式,但它们的应用场景和实现方式有着显著的区别。以下是二者的详细对比:
1. 意图和应用场景
- 原型模式:
- 意图:通过克隆一个现有的对象来创建新对象,而不是通过实例化类来创建新对象。
- 应用场景:
- 当创建对象的过程非常复杂或昂贵时,可以通过复制(克隆)现有的实例来创建新对象。
- 如果系统中有许多具有相似状态的对象,原型模式可以通过复制现有对象节省初始化时间。
- 适合动态加载类或对象时,用于避免依赖具体的构造函数或复杂的初始化流程。
- 建造者模式:
- 意图:将复杂对象的构建过程分离出来,使得相同的构建过程可以创建不同的对象。
- 应用场景:
- 当对象的创建过程复杂且涉及多个步骤时,通过建造者模式可以控制创建过程。
- 特别适合构建复杂的对象(通常包含多个子对象或多个可选参数)。
- 适用于需要通过不同配置来创建不同种类对象的场景(例如创建同一个产品的不同版本)。
2. 创建对象的方式
- 原型模式:
- 通过复制(克隆)对象来创建新对象。复制操作可以是浅拷贝或深拷贝。
- 主要关注对象的复制过程,而不是构建过程。
- 通常需要实现 clone() 方法或类似的克隆机制来复制对象。
- 建造者模式:
- 通过构造步骤逐步构建对象。这个过程将对象的创建过程与表示过程解耦,允许一步一步地配置对象。
- 主要关注构建过程中的不同步骤和顺序,并且允许通过同一个构造过程生成不同的对象。
- 通常使用一个 Builder 类来定义构建的步骤和最终产品的生成。
3. 结构上的区别
- 原型模式:
- 原型模式的核心是对象本身,它使用现有的对象作为原型,通过克隆的方式生成新对象。
- 类结构较为简单,通常只涉及一个需要克隆的对象类。
- 建造者模式:
- 建造者模式有清晰的角色划分,通常包括:
- Builder:定义了构建产品的抽象步骤。
- ConcreteBuilder:实现具体的构建步骤。
- Director(可选):负责控制对象构建的顺序。
- Product:最终生成的对象。
- 结构较复杂,因为构建过程需要清晰的步骤和相应的实现。
- 建造者模式有清晰的角色划分,通常包括:
4. 修改对象状态的方式
- 原型模式:
- 对象状态是通过克隆现有对象,然后可能在新对象上进行少量修改来实现的。
- 这种模式下,通常不涉及构建复杂对象的多个步骤,而是从已有的对象开始,进行轻微的调整。
- 建造者模式:
- 对象状态的创建是通过一系列构建步骤来完成的。这些步骤可以独立控制,允许在构造过程中自由地改变对象的状态。
- 对象的不同部分可以通过不同的步骤来进行定制,构建过程可以灵活调整。
5. 代码示例
原型模式示例(C++):
cpp
#include <iostream>
#include <string>
#include <memory>
class Prototype {
public:
virtual ~Prototype() {}
virtual std::shared_ptr<Prototype> clone() const = 0;
virtual void print() const = 0;
};
class ConcretePrototype : public Prototype {
private:
std::string name;
public:
ConcretePrototype(const std::string& name) : name(name) {}
std::shared_ptr<Prototype> clone() const override {
return std::make_shared<ConcretePrototype>(*this); // 浅拷贝
}
void print() const override {
std::cout << "Prototype: " << name << std::endl;
}
};
int main() {
std::shared_ptr<Prototype> prototype = std::make_shared<ConcretePrototype>("Original");
std::shared_ptr<Prototype> clone = prototype->clone(); // 克隆对象
prototype->print();
clone->print(); // 输出与原型类似的对象
return 0;
}
建造者模式示例(C++):
cpp
#include <iostream>
#include <string>
// 产品类
class Product {
private:
std::string partA;
std::string partB;
public:
void setPartA(const std::string& part) { partA = part; }
void setPartB(const std::string& part) { partB = part; }
void show() const {
std::cout << "Product with " << partA << " and " << partB << std::endl;
}
};
// Builder 接口
class Builder {
public:
virtual ~Builder() {}
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual Product getResult() = 0;
};
// 具体的 Builder 实现
class ConcreteBuilder : public Builder {
private:
Product product;
public:
void buildPartA() override {
product.setPartA("Part A");
}
void buildPartB() override {
product.setPartB("Part B");
}
Product getResult() override {
return product;
}
};
// Director 类,负责构建过程的控制
class Director {
private:
Builder& builder;
public:
Director(Builder& builder) : builder(builder) {}
void construct() {
builder.buildPartA();
builder.buildPartB();
}
};
int main() {
ConcreteBuilder builder;
Director director(builder);
director.construct();
Product product = builder.getResult();
product.show(); // 输出构建后的产品
return 0;
}
6. 总结对比
|------|--------------------|----------------------------|
| 模式 | 原型模式 | 建造者模式 |
| 意图 | 通过复制现有对象来创建新对象。 | 通过分步骤构建复杂对象。 |
| 创建方式 | 克隆(浅拷贝或深拷贝)现有对象。 | 按步骤逐步构建对象。 |
| 结构 | 结构较简单,通常只有一个类实现克隆。 | 结构较复杂,通常涉及多个类和多个步骤。 |
| 状态修改 | 通过克隆对象后修改少量状态。 | 通过多个步骤灵活调整对象的各个部分。 |
| 应用场景 | 当对象创建昂贵且需要复制现有对象时。 | 当对象构建过程复杂,需要逐步构建或有多种构建方式时。 |
解释:
- 原型模式:
- Prototype 是一个抽象类,定义了 clone() 方法。
- ConcretePrototype 是具体的实现类,负责实现 clone() 方法并执行对象的复制操作。
- 建造者模式:
- Builder 是一个接口,定义了构建产品的方法。
- ConcreteBuilder 实现了 Builder 接口,具体构建 Product 的各个部分。
- Director 负责控制构建过程,使用 Builder 来构建最终产品。
- Product 是最终生成的产品类,包含构建的各个部分。
两者的主要区别在于创建对象的方式和灵活性,原型模式专注于现有对象的复制,而建造者模式专注于通过步骤构建复杂对象。