简单工厂模式学习
什么是简单工厂模式?
简单工厂模式在实际项目中非常常见,是一种比较好的编程习惯。它的特点用一句话概括就是:
"当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,创建细节无需知道。"
举个例子:
如果一个软件系统可以提供多个外观不同的水果按钮(如苹果按钮、橙子按钮、香蕉按钮),如下图,这些按钮都源自一个基类,只不过在继承基类后不同的子类修改了部分属性使得它们可以呈现不同的外观。如果我们希望在使用这些按钮时,不需要知道这些按钮的名字,只需要知道表示该按钮的参数,并提供一个调用方法,把参数传入方法中就可以返回一个相对应的按钮对象。 这就是一个简单工厂模式。
简单工厂模式,又称静态工厂方法,它可以根据参数不同来返回不同类的实例,通过专门定义一个类来负责创建其他实例,被创建的实例都有同样的父类。
简单工厂模式的三个角色:
- 工厂角色:负责实现创建所有具体产品的实例
- 抽象产品角色:所有具体产品角色的父类,实现描述所有实例的接口
- 具体产品角色:继承自抽象产品角色,实现某个具体实例
参考:深入浅出设计模式——简单工厂模式(Simple Factory).
简单工厂模式实例解析
举例场景:实现一个计算器,能根据你输入的数字和运算符,输出相应运算符下的计算结果。
抽象产品角色
#include <iostream>
#include <tr1/memory>
using namespace std;
class Operation
{
private:
double A, B;
public:
double GetA() const {return A;}
double GetB() const {return B;}
void SetA(double x) {A=x;}
void SetB(double y) {B=y;}
double virtual GetResult(){return 0;} //子类做各自实现
Operation():A(0), B(0){}
};
具体产品角色
class Add : public Operation
{
public:
double GetResult()
{
return GetA()+GetB();
}
};
class Sub : public Operation
{
public:
double GetResult()
{
return GetA()-GetB();
}
};
class Mul : public Operation
{
public:
double GetResult()
{
return GetA()*GetB();
}
};
class Div : public Operation
{
public:
double GetResult()
{
return GetA()/GetB();
}
};
工厂角色及调用
class SimpleFactory
{
public:
static Operation * CreateOpeartor(char ch)
{
Operation * p;
switch(ch)
{
case '+':
p = new Add();
break;
case '-':
p = new Sub();
break;
case '*':
p = new Mul();
break;
case '/':
p = new Div();
break;
}
return p;
}
};
int main(int argc, char *argv[])
{
double A = 0;
double B = 0;
char ch = '\0';
cin>>A>>ch>>B;
tr1::shared_ptr<Operation> op(SimpleFactory::CreateOpeartor(ch));
op->SetA(A);
op->SetB(B);
cout<<op->GetResult()<<endl;
}
模式优缺点
优点:
- 实现使用专门的工厂类用于创建对象,调用者无需创建使用对象,仅仅“消费”即可;
- 实现明确的责任分割。
缺点
- 简单工厂模式最大的问题在于工厂角色的职责相对过重,增加新的实例需要修改工厂角色代码的判断逻辑,与开闭原则想违背;
- 工厂角色集中了大量创建逻辑,一定程度上增加了系统的复杂度,且一旦此模块不能正常工作,会影响到整个系统;
简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。
简单工厂的适用环境
- 工厂角色负责创建的对象比较少,不会造成工厂方法中的业务逻辑太过复杂;
- 调用者无需关心对象是如何创建的,无需知道类名,只需要知道类型对应的参数。
参考
梦想还是要有的,万一实现了呢~ヾ(◍°∇°◍)ノ゙~~~~~~~~