从开闭原则看工厂模式
来源:互联网 发布:excel从网站导入数据 编辑:程序博客网 时间:2024/05/17 03:57
开闭模式是指对扩展开放,对修改关闭,说的更通俗点,就是说开发了一个软件,应该可以对它进行功能扩展(开放),而在进行这些扩展的时候,不需要对原来的程序进行修改(关闭)!
比如说,我们要做一个客户订购水果的流程,根据面向对象的原则,我们分别创建如下类,基类Fruit,Fruit的派生类Apple,Pear,Orange。客户类Customer,订购水果的流程分为生产水果和打包水果,Customer类的实现大体如下:
class Customer
{
public:
void OrderFruit(const string type)
{
Fruit* pfruit;
if( type == “Apple”)
pfruit = new Apple();
else if( type == “Pear”)
pfruit == new Pear();
else if( type == “
pfruit == new
pfruit->box();
}
};
这样,比如我们需要生产新的水果,比如banana,我们就得在这里添加创建banana的代码,当然这就违反了开闭原则的关闭对已有程序的修改原则。在OO里还有一条原则是说,找出程序中需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。我们很容易知道,生产水果可能是要发生变化的(添加新种类的水果),于是,我们把它封装在一个新的对象类,这个类的每个对象我们称之为Factory,如下:
class SimpleFruitFactory
{
Fruit* ProduceFruit(const string& type)
{
Fruit* pfruit;
if( type == “Apple”)
pfruit = new Apple();
else if( type == “Pear”)
pfruit == new Pear();
else if( type == “
pfruit == new
return pfruit;
}
};
这样,Customer的代码就得到了简化。
class Customer
{
public:
Customer(SimpleFruitFactory* factory)
{
m_factory = factory;
}
void OrderFruit(const string type)
{
Fruit* pfruit;
if( type == “Apple”)
pfruit = new Apple();
else if( type == “Pear”)
pfruit == new Pear();
else if( type == “
pfruit == new
pfruit->box();
}
private:
SimpleFruitFactory* m_factory;
};
经过这层简单的封装,水果的生产就可以有新的客户,而客户在也再不需要知道水果生产的细节。但从开闭原则分析,还是要改变已有的代码。为了真正实现对修改的关闭,我们为每一类型的水果都实现一个Factory(这里已不再是先前的简单工厂,故去掉前缀Simple),AppleFactory,PearFactory和OrangeFactory,它们都继承自一个基类FruitFactory。为了便于管理,我们为每个具体创建的产品都起一个名字,并且可以为工厂添加一个可以得到创建产品类型的接口,如下:
class FruitFactory
{
public:
Fruit* CreateInstance(const string& name) = 0;
void DestroyInstance(Fruit* pfruit) = 0;
const string& GetType()const = 0;
};
class AppleFactory: public FruitFactory
{
public:
Fruit* CreateInstance(const string& name)
{
return new Apple(name);
}
const string& GetType()const
{
return FACTORY_TYPE_NAME;
}
void DestroyInstance(Fruit* pfruit)
{
delete pfruit;
}
static string FACTORY_TYPE_NAME;
};
string AppleFactory::FACTORY_TYPE_NAME = "Apple";//在源文件中指明所创建产品类型
class PearFactory: public FruitFactory
{
public:
Fruit* CreateInstance(const string& name)
{
return new Pear(name);
}
const string& GetType()const
{
return FACTORY_TYPE_NAME;
}
void DestroyInstance(Fruit* pfruit)
{
delete pfruit;
}
static string FACTORY_TYPE_NAME;
};
string PearFactory::FACTORY_TYPE_NAME = "Pear";//在源文件中指明所创建产品类型
OrangeFactory类的实现同上……
有了这样的设计,要添加生产新的水果,我们只要实现新的工厂类,并让他派生自FruitFactory,而无需修改现有的代码。为了让创建对象的过程更加便于使用,我们提供一个外观类Façade。
class Façade
{
protected:
typedef std::map<string,FruitFactory*> FruitFactoryMap;
FruitFactoryMap mFruitFactoryMap;
public:
void addFruitFactory(FruitFactory* fact,bool overrideExisting);
void removeFruitFactory(FruitFactory* fact);
bool hasFruitFactory(const string& typeName)
FruitFactory* getFruitFactory(const string& typeName);
};
这样,通过次外观类,我们就可以很容易的管理对象的各种水果的生产了。从Façade的定义可以看出,Façade内部维护了一个水果的工厂列表,如果需要什么样的水果,怎从该水果列表中得到该水果的工厂对象,如果该工厂不存在,则创建该工厂,并添加到该列表中。Façade类负责生成所有种类的水果,因此它通常会被设计为单体。所以,一般在Façade的构造函数中就会把最常见的水果工厂添加到Façade的内部的列表里。有了Façade类的介入,再来看看Customer是如何来生成水果的。
//比如需要生产Apple
class Customer
{
public:
……
void OrderFruit(const string type)
{
FruitFactory* factory = getFruitFactory(type);
Fruit *apple1 = factory->CreateInstance(“Apple
apple1->box();
}
……
};
有以上可以看出,因为有了工厂方法,Customer代码只需要提供要创建水果的类型,就能得到想要的水果。如果要添加新的水果,仅需要想水果工厂列表中添加新的工厂。
- 从开闭原则看工厂模式
- 开闭原则与工厂模式
- c++工厂模式与开闭原则
- 抽象工厂模式与开闭原则
- 关于简单工厂模式与开闭原则的讨论(1)
- 抽象工厂模式的“开闭原则”倾斜性
- 设计模式开闭原则
- 设计模式--开闭原则
- 设计模式--开闭原则
- 设计模式---->开闭原则
- 设计模式--开闭原则
- 设计模式:开闭原则
- 设计模式开闭原则
- 设计模式--开闭原则
- 简单工厂模式及实例之三个原则(开闭原则,依赖倒转原则,迪米特法则)
- 抽象工厂模式(五):“开闭原则”的倾斜性,抽象工厂模式总结
- 设计模式学习(简单工厂、策略模式、单一职责、开闭原则)
- 模式 开闭原则与哲学
- 悟透JavaScript
- 跨平台开发环境REALbasic内幕:插件与程序编译
- javamail 发送 html邮件
- javamail 补充类
- Linux系统学习方法论
- 从开闭原则看工厂模式
- Drupal学习笔记
- javamail 发送 带附件的 html邮件
- 如果把ape转换成mp3
- 树立目标 坚持不懈——写在来日半周年
- java 实现mysql 的备份与恢复
- 在矩形纸上均匀画点的算法 - 用C++ Builder 6实现
- MySQL 备份和恢复
- 网络编程入门-socket