在面向对象系统设计中经常可以遇到以下的两类问题:
1、为了提高内聚和降低耦合,我们经常会抽象出一些类的公共接口以形成抽象基类或接口。这样我们可以通过声明
一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的一个问题就是n多的子类继承
自抽象基类,我们不得不在每次要用到的子类的地方就编写诸如new xxx;这样的代码。这里带来两个问题:
1)客户程序员必须知道实际子类的名称;
2)程序的扩展性和维护性变得越来越困难。
2、还有一种情况就是父类中并不知道具体要实例化哪一个具体的子类。这里的意思就是,假设我们在类A里要使用到
类 B,B是一个抽象父类,在A中并不知道具体要实例化哪一个B的子类,但是在类A的子类D中是可以知道的。在
A中我们没有办法直接使用类似于new xxx的语句,因为根本不知道xxx是什么。
以上两个问题也就引出了Factory模式的两个最重要的功能:
1、定义创建对象的接口,封装了对象的创建;
2、使得具体化类的工作延迟到了子类中。
对于上面给出的两个问题,我们通常使用SimpleFactory模式来解决。下面就以大话设计模式上的例子来讲讲吧。大
话上的例子是这样的:用面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符,得到结果。那么这里
我们可以抽象出运算操作以及操作数。于是我声明一个抽象基类Operation,具体声明见后面给出的代码,然后每一种
运算都当作它的一个子类。接下来我们需要做的就是声明一个工厂类OperationFactory,来生产运算类。到这里我们
就解决了第一个问题了,实现代码如下:
#include <iostream> #include <string> using namespace std; class Operation { public: virtual double GetResult()=0; void Set(double x, double y) { num1 = x; num2 = y; } protected: double num1, num2; }; class OperationAdd:public Operation { public: double GetResult() { double result = 0.0; result = num1 + num2; return result; } }; class OperationSub:public Operation { double GetResult() { double result = 0.0; result = num1 - num2; return result; } }; class OperationMul:public Operation { double GetResult() { double result = 0.0; result = num1 * num2; return result; } }; class OperationDiv:public Operation { double GetResult() { double result = 0.0; if (0 == num2) { cout << "除数不能为0!" << endl; return 0.0; } else { result = num1 / num2; return result; } } }; class OperationFactory { public: static Operation* CreateOperation(string operation) { Operation* oper = NULL; if ("+" == operation) oper = new OperationAdd(); else if ("-" == operation) oper = new OperationSub(); else if ("*" == operation) oper = new OperationMul(); else if ("/" == operation) oper = new OperationDiv(); return oper; } }; int main() { Operation* oper; oper = OperationFactory::CreateOperation("+"); oper->Set(10, 15); cout << oper->GetResult() << endl; system("pause"); return 0; }
抽象基类Operation,并在工厂类中添加一个判断分支即可。但是这里也不是很完善了,显然工厂类违背了开放-封闭
原则(软件实体可以扩展,但是不可以修改)。每当我们添加运算功能的时候,就必须修改工厂类的判断分支,也就是
说需要对其进行修改。为了解决这个问题,我们可以定义一个抽象基类,把创建运算类的接口定义为纯虚函数,定义
如下:
class IFactory { public: virtual Operation* CreateOperation()=0; };
class AddFactory:public IFactory { Operation* CreateOperation() { return new OperationAdd(); } }; class SubFactory:public IFactory { Operation* CreateOperation() { return new OperationSub(); } }; class MulFactory:public IFactory { Operation* CreateOperation() { return new OperationMul(); } }; class DivFactory:public IFactory { Operation* CreateOperation() { return new OperationDiv(); } };
就可以了。当我们要使用某个运算功能的时候,代码如下:
IFactory* operFactory = new AddFactory; Operation* oper = operFactory->CreateOperation(); oper->Set(15, 30); cout << oper->GetResult() << endl;