工厂设计模式:
顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用new来创建对象,就会对该对象产生强耦合,假如我们需要更换该对象,那么使用该对象的对象都需要进行修改,这显然违背了开闭原则(OCP)。如果我们使用工厂来产生对象,我们只需要与这个工厂打交道就可以了,无需关心具体的对象,达到解耦的目的。
接下来我们从实际的案例出发,从无工厂到有工厂的区别。
eg
有一个销售管理系统支持多种支付方式,如现金支付,信用卡支付,代金券支付等。
在设计过如果不使用简单工厂模式,可能会存在如下的支付方式。
void pay(string pay_type)
{
if(pay_type==现金)
{
现金支付处理手段
}
else if(pay_type==信用卡)
{
信用卡支付处理
}
else if(pay_type==代金券)
{
代金券处理
}
........
}
简单工厂模式包含三个角色:
-
工厂角色(Factory)
-
抽象产品角色(Product)
-
具体产品角色(ConcreteProduct)
简单工厂模式优缺点:
- 由代码可以看出,虽然简单工厂模式一定程度上减少了因需求变更而导致的代码更改,但是实际仍违背了OCP原则。
- 所以简单工厂模式只适合产品对象相对较少,且产品固定的需求,对产品变化无常的需求来说显然不适合。
使用:
// 将各种支付方式写成统一的抽象方法,为各种支付方式提供统一的接口
class AbstractPay
{
public:
virtual void pay() = 0;
};
// 将每种支付方式封装在一个独立的类中,各个支付方式类相对独立修改其一对于其他类没有任何影响,
// 这些独立的支付方式类充当具体的产品类角色。是抽象类的派生类
class CashPay :public AbstractPay
{
public:
void pay()
{
cout << "现金支付" << endl;
}
};
class CreditcardPay :public AbstractPay
{
public:
void pay()
{
cout << "信用卡支付" << endl;
}
};
// 将针对于个种支付方式的对象的创建封装成一个统一的方法中,即:工厂化。
class PayMethodFactory
{
public:
AbstractPay* getPayMethod(string type)
{
if (type == "cash")
{
return new CashPay();
}
else
{
return new CreditcardPay();
}
}
};
int main()
{
PayMethodFactory *pmf = new PayMethodFactory();
//基类指针指向带有虚函数的派生类对象形成多态
AbstractPay* p = pmf->getPayMethod("cash");
//假定现在是现金支付
p->pay();
system("pause");
return 0;
}
工厂方法设计模式:
披萨项目需求变更,客户点披萨时可以点不同口味的披萨。
工厂方法模式的优缺点:
- 让父类的实现延迟到子类中去,减少判断。
- 换汤不换药,和简单工厂模式类似,一般适用于产品对象相对较少,且产品固定的需求。
- 工厂方法一定程度上减轻了工厂的职责,将职责细化,避免工厂类无法正常运行而导致程序崩溃。
eg:
class Operation {
public:
Operation():mNumA(0),mNumB(0){};
virtual ~Operation(){};
virtual double getResult() {
double result = 0;
return result;
}
double mNumA;
double mNumB;
};
class OperationAdd:public Operation{
public:
double getResult(){
double result = 0;
result = mNumA + mNumB;
return result;
}
OperationAdd();
virtual ~OperationAdd();
};
class OperationSub:public Operation{
public:
double getResult(){
double result = 0;
result = mNumA - mNumB;
return result;
}
OperationSub();
virtual ~OperationSub();
};
//---------------------------------
class IFactory {
public:
IFactory();
virtual ~IFactory();
virtual Operation* CreateOperation() = 0;
};
class AddFactory : public IFactory{
public:
AddFactory();
virtual ~AddFactory();
Operation* CreateOperation(){
return new OperationAdd();
}
};
class SubFactory : public IFactory{
public:
SubFactory ();
virtual ~SubFactory ();
Operation* CreateOperation(){
return new OperationSub();
}
};
//---------------------------------
//use
IFactory *f =new AddFactory();
Operation *oper =f->CreateOperation();
oper->mNumA=1;
oper->mNumB=2;
cout<< oper->getResult()<<endl;