工厂方法模式
工厂方法模式 是对之前简单工厂设计上的改进。
先看简单工厂设计的优势:在于工厂内部包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。如工厂设计里面的那个计算器例子,并不需要让客户端管使用那种实例类型,需要那种计算方式,只需要让对应的符号传入工厂就可以了,之后由工厂自动给出对应的实例对象,客户端只用负责计算就可以。但是如果我们想加入新的计算方式,比如说:我现在想计算m的n次方,或者m开根号n。这个时候必须要在工厂类里面加入新的case分支(或者if-else),虽然我们扩展开放了,但是同时修改也开放了,严重违反了开闭原则。
所以对应的,我们引入了工厂方法模式做出相应改进。
工厂方法模式定义
工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一种类。工厂方法使一个类的实例化延迟到一个子类上。
看uml图:
和简单工厂设计的uml图基本上相似,只是把工厂类写成抽象接口类,由抽象工厂类的子类(各个运算 工厂)具体来实例对象。当我们要加入新的运算方式时,只需在运算类和抽象接口工厂类加入对应的子类即可。
工厂方法模式实现时,客户端需要决定实例化那个工厂来实现运算类,选择判断的问题存在,即把工厂内部的判断逻辑交给了客户端来处理,不仅改变了工厂类,同时也需要改变客户端的代码。
代码实现
运算类的代码和之前一模一样。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
class Operation{
protected:
double a,b;
public:
void set_a(double num){
this->a=num;
}
void set_b(double num){
this->b=num;
}
virtual double Getresult(){
double result = 0;
return result;
}
};
class OperationAdd : public Operation{
public:
virtual double Getresult(){
double result = 0;
result = a + b ;
return result;
}
};
class OperationSub : public Operation{
public:
virtual double Getresult(){
double result = 0;
result = a - b ;
return result;
}
};
class OperationMul : public Operation{
public:
virtual double Getresult(){
double result = 0;
result = a * b ;
return result;
}
};
class OperationDiv : public Operation{
public:
virtual double Getresult(){
double result=0;
result = a / b ;
return result;
}
};
此时我们把工厂类改成抽象接口工厂类
class Operation_Factory{
public:
virtual Operation* createOperate() = 0;
};
class addOperation : public Operation_Factory{
public:
Operation* createOperate(){
return new OperationAdd;
}
};
class subOperation : public Operation_Factory{
public:
Operation* createOperate(){
return new OperationSub;
}
};
class mulOperation : public Operation_Factory{
public:
Operation* createOperate(){
return new OperationMul;
}
};
class divOperation : public Operation_Factory{
public:
Operation* createOperate(){
return new OperationDiv;
}
};
所以此时客户端的代码如下
int main(){
Operation_Factory* operation_factory = new addOperation;
Operation* oper = operation_factory->createOperate();
oper->set_a(1),oper->set_b(2);
cout<<oper1->Getresult(); //输出3
}
优点和不足
工厂方法模式的优点在于改变简单工厂模式违反开闭原则的缺点,同时保持其优点,降低了客户端与产品对象的耦合。但是工厂方法模式的缺点同样明显,每当增加一个产品时,就要增加一个产品工厂的类,而且将判断逻辑交给了客户端来处理。