在面向对象系统设计中经常可以遇到以下的两类问题:
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;