目录
什么是工厂模式?
工厂模式(Factory Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定要实例化的具体类是哪一个。工厂模式将对象的创建与使用解耦,使得创建对象的代码更加灵活和可扩展。
工厂模式的核心思想是将对象的创建过程封装起来,通过工厂方法或工厂类来负责创建对象,而不是让客户端代码直接使用 new
操作符去实例化对象。这不仅提高了代码的可维护性,还可以根据具体场景动态地生成不同的对象。
工厂模式的类型
工厂模式主要有以下几种类型:
- 简单工厂模式(Simple Factory Pattern)
-
- 提供一个简单的工厂类,用于根据传入的参数决定创建哪个具体类的对象。虽然简单工厂不属于经典的设计模式,但它是一种常用的对象创建方法。
- 工厂方法模式(Factory Method Pattern)
-
- 工厂方法模式将对象的创建推迟到子类中。每个子类都有自己的一套工厂方法,用于创建特定的对象。
- 抽象工厂模式(Abstract Factory Pattern)
-
- 抽象工厂模式用于创建一系列相关或依赖的对象,而无需指定它们的具体类。它提供了一个接口,可以用于创建多个工厂对象。
工厂模式的设计思想
- 解耦:工厂模式将对象的创建逻辑从使用逻辑中分离,使得对象的创建可以更加灵活和独立。
- 开放-封闭原则:当需要添加新的对象类型时,只需扩展新的工厂类或修改工厂方法,而无需修改客户端代码,符合开放-封闭原则。
- 延迟实例化:工厂模式可以在程序运行时根据特定条件动态地创建对象,支持灵活的实例化策略。
如何使用工厂模式设计对象创建过程
1. 简单工厂模式的实现
简单工厂模式 是最常见的工厂模式,它通过一个单一的工厂类,根据传入的参数来决定实例化哪一个具体类。虽然它不属于 GoF 的 23 种设计模式之一,但在小型应用中非常实用。
简单工厂模式的示例:
假设我们要设计一个系统来创建不同类型的图形对象(如圆形、矩形、三角形),可以使用简单工厂模式来实现图形的创建。
#include <iostream>
#include <memory>
// 抽象产品类,定义接口
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品类:Circle
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle\n";
}
};
// 具体产品类:Rectangle
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "Drawing Rectangle\n";
}
};
// 具体产品类:Triangle
class Triangle : public Shape {
public:
void draw() override {
std::cout << "Drawing Triangle\n";
}
};
// 简单工厂类,用于创建 Shape 对象
class ShapeFactory {
public:
static std::shared_ptr<Shape> createShape(const std::string& type) {
if (type == "circle") {
return std::make_shared<Circle>();
} else if (type == "rectangle") {
return std::make_shared<Rectangle>();
} else if (type == "triangle") {
return std::make_shared<Triangle>();
} else {
return nullptr;
}
}
};
int main() {
// 使用工厂创建不同的 Shape 对象
auto shape1 = ShapeFactory::createShape("circle");
auto shape2 = ShapeFactory::createShape("rectangle");
if (shape1) shape1->draw(); // 输出:Drawing Circle
if (shape2) shape2->draw(); // 输出:Drawing Rectangle
return 0;
}
简单工厂模式的特点:
- 工厂类通过
createShape
方法根据参数类型决定创建哪种具体对象。 - 客户端不直接依赖具体类,而是通过工厂类来获取对象实例。
- 缺点是工厂类的职责单一,当添加新的
Shape
子类时,需要修改工厂类的代码,不符合开放-封闭原则。
2. 工厂方法模式的实现
在工厂方法模式中,工厂的职责被下放到子类,每个子类都有各自的工厂方法,负责创建特定类型的对象。这样可以避免工厂类中的复杂逻辑。
工厂方法模式的示例:
#include <iostream>
#include <memory>
// 抽象产品类
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品类:Circle
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle\n";
}
};
// 具体产品类:Rectangle
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "Drawing Rectangle\n";
}
};
// 抽象工厂类,定义接口
class ShapeFactory {
public:
virtual std::shared_ptr<Shape> createShape() = 0;
virtual ~ShapeFactory() = default;
};
// 具体工厂类:CircleFactory
class CircleFactory : public ShapeFactory {
public:
std::shared_ptr<Shape> createShape() override {
return std::make_shared<Circle>();
}
};
// 具体工厂类:RectangleFactory
class RectangleFactory : public ShapeFactory {
public:
std::shared_ptr<Shape> createShape() override {
return std::make_shared<Rectangle>();
}
};
int main() {
// 创建圆形工厂和矩形工厂
std::shared_ptr<ShapeFactory> circleFactory = std::make_shared<CircleFactory>();
std::shared_ptr<ShapeFactory> rectangleFactory = std::make_shared<RectangleFactory>();
// 通过工厂方法创建具体对象
std::shared_ptr<Shape> circle = circleFactory->createShape();
std::shared_ptr<Shape> rectangle = rectangleFactory->createShape();
circle->draw(); // 输出:Drawing Circle
rectangle->draw(); // 输出:Drawing Rectangle
return 0;
}
工厂方法模式的特点:
- 每个子类工厂负责创建特定类型的对象,符合开放-封闭原则(Open-Closed Principle,OCP),当需要扩展新类型时,只需新增具体工厂类,无需修改原有代码。
- 缺点是需要为每个产品类型提供一个具体的工厂类,当产品类型很多时,工厂类的数量也会增多。
3. 抽象工厂模式的实现
抽象工厂模式 是更复杂的工厂模式,它用于创建一系列相关或依赖的对象。抽象工厂提供了一组创建不同产品的方法,具体工厂则负责实现这些方法。
抽象工厂模式的示例:
假设我们要设计一个系统,它不仅可以创建不同类型的图形(如 Circle
, Rectangle
),还可以创建不同的颜色(如 Red
, Blue
)。我们可以使用抽象工厂模式来实现。
#include <iostream>
#include <memory>
// 图形类接口
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 颜色类接口
class Color {
public:
virtual void fill() = 0;
virtual ~Color() = default;
};
// 具体图形类:Circle
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle\n";
}
};
// 具体图形类:Rectangle
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "Drawing Rectangle\n";
}
};
// 具体颜色类:Red
class Red : public Color {
public:
void fill() override {
std::cout << "Filling Red\n";
}
};
// 具体颜色类:Blue
class Blue : public Color {
public:
void fill() override {
std::cout << "Filling Blue\n";
}
};
// 抽象工厂类,提供创建接口
class AbstractFactory {
public:
virtual std::shared_ptr<Shape> createShape() = 0;
virtual std::shared_ptr<Color> createColor() = 0;
virtual ~AbstractFactory() = default;
};
// 具体工厂类:ShapeFactory
class ShapeFactory : public AbstractFactory {
public:
std::shared_ptr<Shape> createShape() override {
return std::make_shared<Circle>(); // 或者创建其他形状
}
std::shared_ptr<Color> createColor() override {
return nullptr; // ShapeFactory 不创建颜色
}
};
// 具体工厂类:ColorFactory
class ColorFactory : public AbstractFactory {
public:
std::shared_ptr<Shape> createShape() override {
return nullptr; // ColorFactory 不创建形状
}
std::shared_ptr<Color> createColor() override {
return std::make_shared<Red>(); // 或者创建其他颜色
}
};
int main() {
// 创建图形工厂和颜色工厂
std::shared_ptr<AbstractFactory> shapeFactory = std::make_shared<ShapeFactory>();
std::shared_ptr<AbstractFactory> colorFactory = std::make_shared<ColorFactory>();
// 通过工厂创建对象
std::shared_ptr<Shape> shape = shapeFactory->createShape();
std::shared_ptr<Color> color = colorFactory->createColor();
shape->draw(); // 输出:Drawing Circle
color->fill(); // 输出:Filling Red
return 0;
}
抽象工厂模式的特点:
- 通过抽象工厂创建一系列相关的产品对象,提供了更加灵活的对象创建机制。
- 扩展性更强,可以为每种产品族定义新的工厂。
- 缺点是实现起来复杂性更高,需要为每种产品族定义工厂类。
工厂模式的优缺点
优点:
- 解耦对象的创建与使用:工厂模式将对象的创建逻辑与客户端代码分离,客户端无需知道具体类的细节。
- 易于扩展:通过添加新的工厂类或方法,可以轻松扩展系统,符合开放-封闭原则。
- 灵活性:工厂模式允许根据不同的参数或配置,动态地创建不同的对象。
缺点:
- 复杂性增加:工厂模式往往会增加系统的类数量,导致代码变得更加复杂,尤其是当有多个产品类时,工厂类的数量会迅速增长。
- 对新产品的依赖:在简单工厂模式中,如果需要添加新的产品类,可能需要修改工厂类的代码,不符合开放-封闭原则。
总结
- 简单工厂模式:适合小型应用,可以根据传入参数动态创建不同的对象,但工厂类可能过于复杂。
- 工厂方法模式:通过子类提供不同的工厂方法,符合开放-封闭原则,适合需要扩展的场景。
- 抽象工厂模式:适合创建一系列相关的产品对象,为每个产品族提供相应的工厂方法。
工厂模式在设计复杂对象创建逻辑时非常有用,特别是当创建的对象类型较多时,通过工厂模式可以很好地实现对象创建的解耦和扩展。