今天看了一下工厂相关的模式,一个思想就是将对象的创建都放在工厂里,工厂负责生产对象。工厂屏蔽了具体构造了什么对象。
相关的模式有三种:简单工厂模式,工厂模式,抽象工厂模式。
第一种:简单工厂模式
将创建对象的逻辑放在工厂里,以书上计算器的代码为例,以下为简单工厂模式的实现,代码中有相关的解释
//简单工厂模式实现的计算器,
//1 有一个运算的基类,各类运算继承该基类,如果增加新的运算,则只增加子类,不用再更改别的类
//2 一个factory实现实例的创建,在工厂里生产运算类,决定到底使用哪个运算类,不用在客户端进行判断
//优点:将逻辑判断归纳入工厂类,客户端不用管理,
//缺点:增加新的运算后,都要更改工厂类,违反了开放封闭原则(类本身不应修改,开放扩展接口)。
#include <iostream>
using namespace std;
class Operation
{
public:
Operation() : _numberA(0), _numberB(0)
{
}
Operation(double numberA, double numberB)
: _numberA(numberA), _numberB(numberB)
{
}
//别的类通过这两个函数访问私有变量
double GetNumberA()
{
return _numberA;
}
double GetNumberB()
{
return _numberB;
}
//设置私有变量的值
void SetNumberA(double numberA)
{
_numberA = numberA;
}
void SetNumberB(double numberB)
{
_numberB = numberB;
}
//继承类继承的接口
virtual double GetResult()
{
double result = 0.0;
return result;
}
private:
double _numberA;
double _numberB;
};
//继承类不能访问基类的私有成员
class OperationAdd : public Operation
{
public:
double GetResult()
{
return GetNumberA() + GetNumberB();
}
};
class OperationSub : public Operation
{
public:
double GetResult()
{
return GetNumberA() - GetNumberB();
}
};
class OperationMul : public Operation
{
public:
double GetResult()
{
return GetNumberA() * GetNumberB();
}
};
class OperationDiv : public Operation
{
public:
double GetResult()
{
//抛出异常
if (GetNumberB() == 0)
throw exception("除数不能为0");
return GetNumberA() / GetNumberB();
}
};
//工场函数,用于构造实例
class OperationFactory
{
public:
//定义为static类是为了可以使用类名直接访问该函数,
//不用另外定义该类的对象然后访问函数
static Operation* createFactory(char op)
{
//定义一个基类对象的指针,动态决定运行
//时指向哪一个继承类对象,运用了多态。
Operation *oper = NULL;
switch (op)
{
case '+':
oper = new OperationAdd;
break;
case'-':
oper = new OperationSub;
case '*':
oper = new OperationMul;
break;
case '/':
oper = new OperationDiv;
break;
}
return oper;
}
};
int main()
{
Operation *poper = NULL;
//创建一个工厂用于产生对象。
poper = OperationFactory::createFactory('+');
poper->SetNumberA(4);
poper->SetNumberB(9);
cout << poper->GetResult() << endl;
system("pause");
return 0;
}
简单工厂模式最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
缺点是如上面的例子,当我又增加一个新的计算功能,求M的N次方,首先增加一个运算的子类,然后要修改原来的工厂类,加一个swtich case语句,但这违背了开放封闭原则,并不是扩展,而是修改原来的类,所以下面的工厂模式就克服了这个缺点。
第二种:. 工厂模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在,即工厂方法把简单工厂的内部逻辑判断移到了客户端代码进行。如果要加功能,本来是改工厂类的,现在是修改客户端。
适用性:
1 当一个类不知道它所必须创建的对象的类的时候
2 当一个类希望由它的子类来指定它所创建的对象的时候
3 当类将创建对象的职责委托给多个帮助子类中的一个,你希望将哪一个帮助子类是代理这这一信息局部化的时候。
结构图:
参与者:
Product:定义工厂方法所创建爱你的对象的接口
ConcreteProduct :实现product的接口
Creator:声明工厂方法,该方法返回一个product对象。Creator可以定义一个工厂方法的缺省实现,返回一个缺省的ConcreteProduct对象。可以调用工厂方法创建一个Product对象。
ConcreteCreator:重定义共存方法以返回一个ConcreteProduct实例。
协作:
Creator依赖于它的子类来定义工厂方法,所以返回一个适当的ConcreteProduct实例。
效果:
不再将应用有关的类绑定到代码中,代码仅处理Product接口,不用与ConcreteProduct打叫道。但一个潜在的缺点是客户创建了一个具体的子类,就得在增加一个工厂的子类。
实现:
1 主要有两种情况:一种是Creator类是一个抽象类而且不提供所声明的工厂方法的实现,一种是Creator是一个具体的类而且为共存方法提供一个缺省的实现,也可能有一个定义了缺省实现的抽象类,但是不太常见。
2 参数化共存,
4 关于子类创建问题,C++中可以用模板来避免创建子类,将Producr作为模板参数传给StandordCreator,这样避免了子类创建,模板真好。
以下是计算器类的工厂方法实现:
//工厂模式实现的计算器,
//1 有一个运算的基类,各类运算继承该基类,如果增加新的运算,则只增加子类,不用再更改别的类
//2 一个工厂的基类,各个工厂继承该基类,如果增加新的运算,则不用再更改工厂类,而只是添加新的继承类
//优点:解决了简单工厂模式要修改工厂类的问题,即改正了开放封闭原则,
//缺点:增加新的运算后,需要更改客户端的代码,将判断由工厂类移到了客户端
#include <iostream>
using namespace std;
class Operation
{
public:
Operation() : _numberA(0), _numberB(0)
{
}
Operation(double numberA, double numberB)
: _numberA(numberA), _numberB(numberB)
{
}
//别的类通过这两个函数访问私有变量
double GetNumberA()
{
return _numberA;
}
double GetNumberB()
{
return _numberB;
}
//设置私有变量的值
void SetNumberA(double numberA)
{
_numberA = numberA;
}
void SetNumberB(double numberB)
{
_numberB = numberB;
}
//继承类继承的接口
virtual double GetResult()
{
double result = 0.0;
return result;
}
private:
double _numberA;
double _numberB;
};
//继承类不能访问基类的私有成员
class OperationAdd : public Operation
{
public:
double GetResult()
{
return GetNumberA() + GetNumberB();
}
};
class OperationSub : public Operation
{
public:
double GetResult()
{
return GetNumberA() - GetNumberB();
}
};
class OperationMul : public Operation
{
public:
double GetResult()
{
return GetNumberA() * GetNumberB();
}
};
class OperationDiv : public Operation
{
public:
double GetResult()
{
//抛出异常
if (GetNumberB() == 0)
throw exception("除数不能为0");
return GetNumberA() / GetNumberB();
}
};
//工厂函数的基类,其他工厂用于继承
class OperationFactory
{
public:
virtual Operation *CreateOperation()
{
return NULL;
}
};
class AddFactory : public OperationFactory
{
public:
Operation* CreateOperation()
{
return new OperationAdd;
}
};
class SubFactory : public OperationFactory
{
public:
Operation* CreateOperation()
{
return new OperationSub;
}
};
class MulFactory : public OperationFactory
{
public:
Operation* CreateOperation()
{
return new OperationMul;
}
};
class DivFactory : public OperationFactory
{
public:
Operation* CreateOperation()
{
return new OperationDiv;
}
};
int main()
{
Operation *poper = NULL;
//需要更改这里的代码
OperationFactory *operf = new DivFactory;
poper = operf->CreateOperation();
poper->SetNumberA(27);
poper->SetNumberB(9);
cout << poper->GetResult() << endl;
system("pause");
return 0;
}