「软件设计模式」工厂方法模式(Factory Method) vs 抽象工厂模式(Abstract Factory)
前言
在软件工程领域,设计模式是解决常见问题的经典方案。本文将深入探讨两种创建型模式:工厂方法模式和抽象工厂模式,通过理论解析与实战代码示例,帮助开发者掌握这两种模式的精髓。
一、工厂方法模式(Factory Method Pattern)
1.1 模式思想
工厂方法模式的核心在于将对象的创建延迟到子类,通过定义创建对象的接口,让子类决定实例化哪个类。这种模式完美体现了依赖倒置原则。
1.2 模式结构
- Product:抽象产品接口
- ConcreteProduct:具体产品实现
- Creator:抽象创建者
- ConcreteCreator:具体创建者
1.3 代码示例
#include <iostream>
#include <string>
class Shape {
public:
virtual void draw() = 0;
};
class Circle : public Shape {
void draw() {
std::cout << "Circle::draw()" << std::endl;
}
};
class Rectangle : public Shape {
void draw() {
std::cout << "Rectangle::draw()" << std::endl;
}
};
class Square : public Shape {
void draw() {
std::cout << "Square::draw()" << std::endl;
}
};
class ShapeFactory {
public:
Shape* getShape(const std::string& shapeType) {
if (shapeType.empty()) {
return nullptr;
}
if (shapeType == "CIRCLE") {
return new Circle();
} else if (shapeType == "RECTANGLE") {
return new Rectangle();
} else if (shapeType == "SQUARE") {
return new Square();
}
return nullptr;
}
};
#include "factory_mode.h"
int main(int argc, char const* argv[]) {
ShapeFactory* shapeFactory = new ShapeFactory();
Shape* shape1 = shapeFactory->getShape("CIRCLE");
shape1->draw();
Shape* shape2 = shapeFactory->getShape("RECTANGLE");
shape2->draw();
Shape* shape3 = shapeFactory->getShape("SQUARE");
shape3->draw();
delete shapeFactory;
return 0;
}
1.4 运行结果
1.5 适用场景
- 需要灵活扩展产品类型
- 创建过程需要封装处理逻辑
- 需要解耦客户端与具体产品类
二、抽象工厂模式(Abstract Factory Pattern)
2.1 模式思想
抽象工厂模式通过创建相关对象族来提升系统的扩展性,强调产品系列的概念。它比工厂方法模式更高层次的抽象。
2.2 模式结构
- AbstractFactory:抽象工厂接口
- ConcreteFactory:具体工厂实现
- AbstractProduct:抽象产品接口
- ConcreteProduct:具体产品实现
2.3 代码示例
产品定义:
#include <iostream>
#include <string>
//
class Color {
public:
virtual void fill() = 0;
};
class Red : public Color {
public:
void fill() {
std::cout << "Red::fill()" << std::endl;
}
};
class Green : public Color {
public:
void fill() {
std::cout << "Green::fill()" << std::endl;
}
};
class Blue : public Color {
public:
void fill() {
std::cout << "Blue::fill()" << std::endl;
}
};
// 形状产品
class Shape {
public:
virtual void draw() = 0;
};
class Circle : public Shape {
void draw() {
std::cout << "Circle::draw()" << std::endl;
}
};
class Rectangle : public Shape {
void draw() {
std::cout << "Rectangle::draw()" << std::endl;
}
};
class Square : public Shape {
void draw() {
std::cout << "Square::draw()" << std::endl;
}
};
抽象工厂
#include "color.h"
#include "shape.h"
// 抽象工厂
class AbstractFactory {
public:
virtual Shape* getShape(const std::string& shapeType) = 0;
virtual Color* getColor(const std::string& colorType) = 0;
};
实体工厂
#include "abstract_factory.h"
// 实体工厂类
// 形状工厂
class ShapeFactory : public AbstractFactory {
public:
Shape* getShape(const std::string& shapeType) {
if (shapeType.empty()) {
return nullptr;
}
if (shapeType == "CIRCLE") {
return new Circle();
} else if (shapeType == "RECTANGLE") {
return new Rectangle();
} else if (shapeType == "SQUARE") {
return new Square();
}
return nullptr;
}
Color* getColor(const std::string& colorType) {
return nullptr;
}
};
// 颜色工厂
class ColorFactory : public AbstractFactory {
public:
Color* getColor(const std::string& colorType) {
if (colorType.empty()) {
return nullptr;
}
if (colorType == "RED") {
return new Red();
} else if (colorType == "GREEN") {
return new Green();
} else if (colorType == "BLUE") {
return new Blue();
}
return nullptr;
}
Shape* getShape(const std::string& shapeType) {
return nullptr;
}
};
生产商:
#include "factory.h"
class FactoryProducer {
public:
static AbstractFactory* getFactory(const std::string& choice) {
if (choice == "SHAPE") {
return new ShapeFactory();
} else if (choice == "COLOR") {
return new ColorFactory();
}
return nullptr;
}
};
main:
#include "producer.h"
// 抽象工厂 demo
int main(int argc, char const* argv[]) {
AbstractFactory* shapeFactory = FactoryProducer::getFactory("SHAPE");
Shape* shape1 = shapeFactory->getShape("CIRCLE");
shape1->draw();
Shape* shape2 = shapeFactory->getShape("RECTANGLE");
shape2->draw();
Shape* shape3 = shapeFactory->getShape("SQUARE");
shape3->draw();
AbstractFactory* colorFactory = FactoryProducer::getFactory("COLOR");
Color* color1 = colorFactory->getColor("RED");
color1->fill();
Color* color2 = colorFactory->getColor("GREEN");
color2->fill();
Color* color3 = colorFactory->getColor("BLUE");
color3->fill();
delete shapeFactory;
delete colorFactory;
return 0;
}
2.4 运行结果
2.5 适用场景
- 需要创建多个相关对象组成的系列
- 系统需要支持不同产品族的切换
- 产品对象之间存在约束关系
三、核心差异对比
维度 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|
抽象层次 | 单个产品创建 | 产品族创建 |
扩展方向 | 垂直扩展(新增产品类型) | 水平扩展(新增产品族) |
实现方式 | 继承 | 组合 |
系统复杂度 | 简单 | 复杂 |
典型应用场景 | 日志记录器、支付方式 | 跨平台UI组件、数据库访问 |
四、模式选择指南
-
选择工厂方法模式当:
- 需要解耦客户端与具体产品类
- 系统需要支持多种同类产品的创建
- 产品类型相对单一
-
选择抽象工厂模式当:
- 需要创建多个相互关联的产品
- 需要保证产品之间的兼容性
- 系统需要支持不同产品族的切换
五、最佳实践建议
- 优先使用工厂方法:当产品结构简单时,避免过度设计
- 注意开闭原则:通过扩展而非修改来增加新产品
- 使用依赖注入:结合Spring等框架实现更灵活的工厂管理
- 文档化产品族:明确各产品之间的约束关系
- 性能考量:复杂工厂实现需要考虑对象池等优化手段
结语
掌握工厂模式是成为架构师的重要阶梯。工厂方法模式像专业工匠,专注单一产品的精雕细琢;抽象工厂模式如生产总监,统筹协调整个产品家族。理解它们的差异,才能在系统设计中做出最合适的选择。