上回《大话设计模式C++版——简单工厂模式》中指出了简单工厂模式的缺陷,即违背了开发—封闭原则,其主要原因是由于switch的判断结构的使用,使修改或添加新的对象时需要改动简单工厂类的代码,如何改造switch结构,表驱动法就可以粉墨登场了。

表驱动法的介绍见《数据驱动编程之表驱动法》。

1、面向接口编程,先改造抽象接口类IOperation

class IOperation
{
public:
IOperation() : m_nNuml(0), m_nNumr(0) {}
virtual ~IOperation() {} virtual void SetNum(int nNuml = 0, int nNumr = 0)
{
m_nNuml = nNuml;
m_nNumr = nNumr;
} virtual int CalculateResult() = 0; public:
typedef IOperation* (CALLBACK* fn_CreateObject)(); protected:
int m_nNuml, m_nNumr;
};

接口基本无改动,由于表驱动法中需要在表中填入驱动函数接口,故先定义一个该接口函数的定义,用于产生具体接口对象。

2、改造接口对象类

class COperation_Add : public IOperation
{
public:
int CalculateResult()
{
return m_nNuml + m_nNumr;
} static IOperation* CALLBACK CreateObject()
{
return new COperation_Add();
}
}; class COperation_Dec : public IOperation
{
public:
int CalculateResult()
{
return m_nNuml - m_nNumr;
} static IOperation* CALLBACK CreateObject()
{
return new COperation_Dec();
}
};

增加了CreateObject()静态函数,改函数的作用是用来产生本对象。由于表驱动函数是用于回调的,所以需要定义为静态回调函数。

3、改造工厂类,增加驱动表改造switch结构(重点)

class CClassFactory
{
public:
CClassFactory() {}
virtual ~CClassFactory() {} BOOL AddOperationFunc(char cOperation, IOperation::fn_CreateObject func)
{
if (func)
{
m_mapOperationFunc[cOperation] = func;
return TRUE;
} return FALSE;
} IOperation* CreateObject(char cOperation)
{
IOperation::fn_CreateObject func = m_mapOperationFunc[cOperation]; if (func)
{
return func();
} return NULL;
} protected:
std::map<char, IOperation::fn_CreateObject> m_mapOperationFunc; //用map实现驱动表
};

工厂类中的switch消失了,换成了在map中以操作符为key找对应驱动函数,然后进行调用。同时增加了添加新操作符和对应驱动函数的接口AddOperationFunc(),这样如果需要新增加对象或者修改操作符对应的驱动函数,调用此接口即可,灵活性大大增加。

4、使用示例

void	Test()
{
CClassFactory oCClassFactory;
IOperation* poIOperation = NULL; //添加对象工厂的生产对象
oCClassFactory.AddOperationFunc('+', COperation_Add::CreateObject);
oCClassFactory.AddOperationFunc('-', COperation_Dec::CreateObject); poIOperation = oCClassFactory.CreateObject('+'); if (poIOperation)
{
poIOperation->SetNum(2, 3);
printf("2 + 3 = %d\n", poIOperation->CalculateResult()); delete poIOperation;
} poIOperation = oCClassFactory.CreateObject('-'); if (poIOperation)
{
poIOperation->SetNum(2, 3);
printf("2 + 3 = %d\n", poIOperation->CalculateResult()); delete poIOperation;
}
}

使用前需添加操作符和对应的驱动函数,这样一来将用户的任务加重了,而且需要用户认识的类增加了,封装性降低了。是否可进一步改进?

5、进一步改进简单工厂类,提高封装性

class CNewClassFactory : CClassFactory
{
public:
virtual ~CNewClassFactory() {} virtual void Init()
{
AddOperationFunc('+', COperation_Add::CreateObject);
AddOperationFunc('-', COperation_Dec::CreateObject);
}
};

新简单工厂类中,增加了一个初始化函数Init(),代替用户的进行操作符和对应的驱动函数,这样用户只需要调用Init()函数即可,封装性进一步提高,那么有同学可能会问,如果要增加新的计算对象,还不得改动Init()函数代码,这不跑了一圈又回到没改造前的原点了。

这就得用到开放—封闭原则了,新简单工厂类CNewClassFactory中,我们将Init()函数申明为虚函数了,如果我们要增加新的计算对象,可以有2个途径:

5.1用户在自己代码中调用AddOperationFunc()函数进行添加。

5.2继承新简单工厂类,重写Init()函数。

大话设计模式C++版——表驱动法改造简单工厂的更多相关文章

  1. 大话设计模式C++实现-第1章-简单工厂模式

    一.UML图 二.包括的角色 简单工厂模式包括三个角色: (1)工厂类Factory:工厂类是用来制造产品的. 因此,在Factory中有一个用于制造产品的Create函数或者Generate函数之类 ...

  2. 大话设计模式C++版——简单工厂模式

    简单工厂模式应该是所有设计模式中最简单,也最基础的一种模式,以下是一个简单的采用工厂模式写一个加减法的计算器. 1.抽象接口类——依赖倒转原则(高层和底层都要依赖于抽象,针对接口编程) class I ...

  3. 大话设计模式C++版——工厂模式在COM中的典型应用

    上篇<大话设计模式C++版——抽象工厂模式>中,我们拯救世界未遂,留下小小的遗憾,本篇中我们将给出一个解决方案——COM组件技术,同时也顺便扯扯工厂模式在COM组件技术中的应用. 工厂模式 ...

  4. 大话设计模式C++版——抽象工厂模式

    前面说过,简单工厂模式是最基础的一种设计模式,那以工厂命名的设计模式就是23种设计模式中最多的一种,他们一脉相承,一步一步进化而来,这里就是其中的最后一种——抽象工厂模式(Abstract Facto ...

  5. 大话设计模式C++版——代理模式

    本篇开始前先发个福利,程杰的<大话设计模式>一书高清电子版(带目录)已上传至CSDN,免积分下载. 下载地址:http://download.csdn.net/detail/gufeng9 ...

  6. 大话设计模式C++版——工厂方法模式

    工厂方法模式是以简单工厂模式为基础的,如果未了解简单工厂模式的同学可先浏览<大话设计模式C++版——简单工厂模式>.在简单工厂模式中,提到过简单工厂模式的缺陷,即违背了开发—封闭原则,其主 ...

  7. Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...

  8. 设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)

    什么是简单工厂模式? 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式.通过专门定义一个类来负责创建其它类的实例,被创建的实例 ...

  9. 大话设计模式C++版——原则和引言

    转贴请注明转自:http://blog.csdn.net/gufeng99/article/details/45832711 读程杰的<大话设计模式>有一段时间了,将其C#版的设计模式代码 ...

随机推荐

  1. 常见.NET功能代码汇总

    1,在Web上修改指定文件位置的Web.config 这里需要使用 WebConfigurationManager 类,但必须使用WebConfigurationFileMap类来指定文件位置,看代码 ...

  2. Send push notification on Apple (APNS) on c#.net

    原文: http://apns-c-sharp-net-vikram-jain.blogspot.com ======================= Please, Install your ce ...

  3. 你可能不需要 jQuery!使用原生 JavaScript 进行开发

    很多的 JavaScript 开发人员,包括我在内,都很喜欢 jQuery.因为它的简单,因为它有很多丰富的插件可供使用,和其它优秀的工具一样,jQuery 让我们开发人员能够更轻松的开发网站和 We ...

  4. 图标集锦:10套免费的社交媒体 & 社交网站图标

    社交网络是最近几年互联网领域最热门的关键词之一,如今社会网络化媒体也成为我们信息获取和传播的重要途径,很多网站都有把内容分享到社交媒体的功能. 社交媒体图标作为向用户传递信息的重要媒介,不管是在网页还 ...

  5. HTML5 Content Editable实践

    基于此开发文档:https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Content_Editable 问题:通过contenteditabl ...

  6. 批量另存mxd

    在GIS数据处理中,批量操作是经常遇到的问题,Python脚本是解决问题的最好方法.现在需要将arcgis10.1的mxd另存为10.0,不仅数量较多,而且每个mxd要素和标注非常多,手动来操作确实慢 ...

  7. SP2013 SP1(kb28805502)补丁安装测试初体验

    安装完SP1(kb28805502)第一印象是整体页面加载浏览速度非常快了,在笔记本建立的虚拟机能达到肉眼感觉不到卡顿真的是非常快了. 1.新添加了页面个性化设置功能菜单 3.默认访问网站的页面显示, ...

  8. MySQL Performance tuning

    1.表级锁状态 mysql> show status like 'table%'; +----------------------------+-----------+ | Variable_n ...

  9. 小技巧,如何在Label中显示图片

    这个需求其实是有的,比如QQ聊天界面里面发送的信息,可以用label来显示文字(也可以用button显示),但是有时候用户可能会发送图片.如果能让Label遇到文字就显示文字,遇到图片就显示图片就好了 ...

  10. Swift设置自动行高

    // 设置行高自适应 tableView.rowHeight = UITableViewAutomaticDimension // 设置预估行高 tableView.estimatedRowHeigh ...