一、工厂模式(Factory Pattern)
核心思想
将对象的创建逻辑封装在一个工厂类中,客户端只需通过工厂获取对象,而无需关心具体的创建过程。
应用场景
-
对象创建过程复杂
当对象的创建需要大量初始化代码或依赖外部资源时,使用工厂模式将创建逻辑集中管理。
示例:数据库连接对象的创建,需要配置 URL、用户名、密码等参数。 -
根据条件动态创建对象
根据不同的条件(如配置、用户输入)创建不同类型的对象。
示例:游戏中根据用户选择的角色类型(战士、法师、射手)创建对应的角色对象。 -
解耦对象的使用和创建
当对象的具体实现可能频繁变化时,使用工厂模式可以避免客户端代码的修改。
示例:支付系统支持多种支付方式(微信、支付宝、银联),通过工厂统一创建支付对象。 -
框架或库的扩展点
框架提供工厂接口,允许用户自定义对象的创建方式。
示例:Spring 框架中的BeanFactory
,通过配置文件动态创建 Bean 对象。
代码示例
// 工厂模式示例:创建不同类型的图形
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() override { std::cout << "Drawing Circle" << std::endl; }
};
class Rectangle : public Shape {
public:
void draw() override { std::cout << "Drawing Rectangle" << std::endl; }
};
class ShapeFactory {
public:
static Shape* createShape(const std::string& type) {
if (type == "circle") return new Circle();
if (type == "rectangle") return new Rectangle();
return nullptr;
}
};
// 使用工厂创建对象
Shape* circle = ShapeFactory::createShape("circle");
circle->draw(); // 输出: Drawing Circle
二、建造者模式(Builder Pattern)
核心思想
将一个复杂对象的构建与表示分离,允许用户通过指定复杂对象的类型和内容,一步一步构建它们。
应用场景
-
对象有多个可选参数或复杂配置
当对象的构造函数参数过多(超过 4 个)或参数组合复杂时,使用建造者模式可以避免构造函数膨胀。
示例:创建一个配置对象,包含主机名、端口、超时时间、认证信息等多个可选参数。 -
需要按步骤构建对象
对象的构建过程需要多个步骤(如初始化、配置、验证),且步骤顺序可能不同。
示例:游戏角色的创建需要依次设置外观、装备、技能等属性。 -
创建不可变对象
确保对象在创建过程中不会被中途修改,只能在完全构建后使用。
示例:创建一个User
对象,要求所有字段在初始化后不可变。 -
构建不同表示的同一对象
同一构建过程可以创建不同配置的对象。
示例:构建一个汽车对象,可以选择不同的引擎、轮胎、内饰等组合。
代码示例
// 建造者模式示例:创建复杂的配置对象
class ServerConfig {
private:
std::string host;
int port;
bool ssl;
int timeout;
public:
class Builder {
private:
std::string host;
int port = 80; // 默认值
bool ssl = false;
int timeout = 3000;
public:
Builder& setHost(const std::string& h) { host = h; return *this; }
Builder& setPort(int p) { port = p; return *this; }
Builder& enableSSL(bool s) { ssl = s; return *this; }
Builder& setTimeout(int t) { timeout = t; return *this; }
ServerConfig build() {
return ServerConfig(host, port, ssl, timeout);
}
};
private:
ServerConfig(const std::string& h, int p, bool s, int t)
: host(h), port(p), ssl(s), timeout(t) {}
};
// 使用建造者创建配置对象
ServerConfig config = ServerConfig::Builder()
.setHost("example.com")
.setPort(443)
.enableSSL(true)
.setTimeout(5000)
.build();
三、对比与选择
维度 | 工厂模式 | 建造者模式 |
---|---|---|
核心目的 | 封装对象的创建逻辑 | 分步构建复杂对象 |
创建过程复杂度 | 简单或中等(一次性创建) | 复杂(多步骤、顺序可能不同) |
关注点 | 快速创建对象 | 精细化控制对象的构建过程 |
返回对象 | 通常直接返回产品 | 通过 Builder 链式调用,最后调用 build () |
适用场景 | 对象类型差异大、创建逻辑集中 | 对象参数多、需要分步配置 |
四、实际开发中的典型案例
-
工厂模式案例
- Spring 框架:
BeanFactory
根据配置文件创建 Bean 实例。 - Java 的
Calendar
类:Calendar.getInstance()
根据时区和语言环境创建不同的日历实现。 - 游戏开发:根据敌人类型(普通、精英、Boss)创建不同属性的敌人对象。
- Spring 框架:
-
建造者模式案例
- Java 的
StringBuilder
:通过append()
方法链式构建字符串。 - Guava 库的
ImmutableSet
:使用ImmutableSet.builder()
分步添加元素。 - Android 的
AlertDialog
:通过AlertDialog.Builder
设置标题、内容、按钮等。
- Java 的
五、总结
- 工厂模式适合快速创建不同类型的对象,强调创建的统一性和灵活性。
- 建造者模式适合构建复杂对象,强调分步配置和参数的可选性。
- 在实际开发中,两种模式可以结合使用(如工厂中使用建造者创建复杂对象),以满足更复杂的需求。