设计模式-02 设计模式-工厂模式factory
1.定义
工厂模式是一种创建型设计模式,它定义了一个创建对象的接口,让子类决定实例化哪一个类。
工厂模式使程序不必指定要创建产品的具体类,从而解耦应用程序与实际创建产品的具体类。
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。
工厂模式属于创建型模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离。
.-------------.
| |
| Factory |
'-------------'
|
|
.-------------------------v---------------------.
| |
| ProductA ProductB |
|-----------------------------------------------|
| | |
| ProductA1 | ProductA2 | ProductB1 |
| | | |
.-----------------. | | |
| | v v v |
Client .---> | FactoryMethod | -> ProductA1 -> ProductA2 -> ProductB1
| |
'---------------'
2.内涵
设计原则:
- 单一职责原则:工厂类仅负责创建对象,不负责其他操作。
- 开闭原则:工厂类对扩展开放,对修改关闭。新产品可以轻松添加到工厂中,而无需修改现有代码。
- 依赖倒置原则:应用程序依赖于抽象(工厂类),而不是具体实现(产品类)。
优点:
- 提高代码的灵活性,容易扩展。
- 解耦应用程序与具体创建产品的类。
- 封装产品创建过程,提高了可维护性。
缺点:
- 引入了额外的抽象层,可能会增加代码复杂性。
- 如果需要经常创建新产品,可能会导致大量工厂类。
3.案例对比
bad 设计
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
#include <tuple>
#include <sstream>
#include <memory>
#include <cmath>
using namespace std;
enum class PointType
{
cartesian,polar
};
struct Point
{
/**
* 构造方法
* @param a x or rho
* @param b y or theta
* @param type 根据Type 初始化对象
*/
Point(float a, float b, PointType type = PointType::cartesian)
{
if(type == PointType::cartesian){
x = a;
y = b;
}else {
x = a * cos(b);
y = a * sin(b);
}
}
float x, y;
};
int main()
{
return 0;
}
好的设计
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
#include <tuple>
#include <sstream>
#include <memory>
#include <cmath>
using namespace std;
enum class PointType
{
cartesian,
polar
};
struct Point
{
Point(float x, float y):x(x),y(y){}
public:
float x, y;
static Point NewCartesian(float x, float y) // 静态工厂方法
{
return {x,y};
}
static Point NewPolar(float rho, float theta) // 静态工厂方法
{
return {rho*cos(theta), rho*sin(theta)};
}
friend ostream &operator<<(ostream &os, const Point &point)
{
os << "X:" << point.x << " Y:" << point.y << endl;
return os;
}
};
int main()
{
auto p = Point::NewPolar(5, 3.1415 / 4);
cout << p <<endl;
}
4.注意事项
简单工厂
- 局限性:限制了创建产品的灵活性,仅能创建预先定义好的产品。
- 依赖管理:难以管理创建不同产品所依赖的类和对象。
其他注意事项:
- 职责单一原则:工厂类应仅负责创建产品,避免与其他职责混合。
- 可扩展性:工厂设计应考虑可扩展性,以支持未来添加新产品。
- 可测试性:工厂代码应易于测试,以验证创建产品的正确性。
- 性能瓶颈:如果工厂创建产品需要大量计算或资源,可能会成为性能瓶颈。
- 谨慎使用:工厂模式的过度使用可能会导致代码复杂性和维护成本增加。
5.最佳实践
- 考虑抽象工厂,而不是简单工厂:抽象工厂提供更灵活和可扩展的解决方案。
- 使用反射创建产品:当产品类型在运行时才知道时,反射可以帮助创建产品。
- 利用设计模式组合:将工厂模式与其他模式相结合,例如策略模式或单例模式,以提高代码的可重用性和灵活性。
- 单元测试工厂:使用单元测试验证工厂创建产品的正确性。
- 避免过度使用:只有在确实需要分离产品创建时才使用工厂模式。
6.总结
工厂模式提供了一种创建对象而不指定其具体类的接口。