大话设计模式C++版——抽象工厂模式
前面说过,简单工厂模式是最基础的一种设计模式,那以工厂命名的设计模式就是23种设计模式中最多的一种,他们一脉相承,一步一步进化而来,这里就是其中的最后一种——抽象工厂模式(Abstract Factory),其是在工厂方法模式的基础上改进而来,如果没有弄明白工厂方法模式的同学请先观看《大话设计模式C++版——工厂方法模式》。
为什么会有抽象工厂模式?抽象工厂模式是简单工厂模式缺陷的终极解决方式么?NO,抽象工厂模式并不是为了解决简单工厂模式的缺陷而活着,它是因为有新的使命而诞生。 一个简单的例子,有一个数据库保存着公司员工的信息,为了能够灵活使用各种数据库,将操作数据库的类抽象出来,并采用比简单工厂模式先进那么一点点的工厂方法模式实现。
1、工厂方法模式实现员工信息数据库操作
1.1 员工类和工厂类
typedef struct Employee
{
int nID;
TString tstrName;
}; class IEmployee
{
public:
virtual ~IEmployee() {} virtual bool InserttoDB(Employee& stEmployee) = 0;
virtual Employee GetEmployee(int nID) = 0;
}; class CEmployeefromMysql : public IEmployee
{
public:
bool InserttoDB(Employee& stEmployee)
{
_tprintf(_T("Insert employee %s into mysql\n"), stEmployee.tstrName.c_str());
return true;
} Employee GetEmployee(int nID)
{
Employee stEmployee;
printf("Get an employee from mysql by id %d\n", nID);
return stEmployee;
}
}; class CEmployeefromAccess : public IEmployee
{
public:
bool InserttoDB(Employee& stEmployee)
{
_tprintf(_T("Insert employee %s into access\n"), stEmployee.tstrName.c_str());
return true;
} Employee GetEmployee(int nID)
{
Employee stEmployee;
printf("Get an employee from access by id %d\n", nID);
return stEmployee;
}
}; class IFactory
{
public:
~IFactory() {} virtual IEmployee* CreateEmployee() = 0;
}; class CFactoryfromMysql : public IFactory
{
public:
IEmployee* CreateEmployee()
{
return new CEmployeefromMysql();
}
}; class CFactoryfromAccess : public IFactory
{
public:
IEmployee* CreateEmployee()
{
return new CEmployeefromAccess();
}
};
分别有 Mysql 和 Access 2种数据库的员工对象类和2种工厂对象类。
1.2 使用示例
void Test()
{
IFactory* poIFactory = new CFactoryfromMysql();
IEmployee* poIEmployee = NULL; if (!poIFactory)
{
return;
} poIEmployee = poIFactory->CreateEmployee(); if (poIEmployee)
{
Employee stEmployee; stEmployee.nID = 1;
stEmployee.tstrName = _T("Jim");
poIEmployee->InserttoDB(stEmployee);
delete poIEmployee;
} delete poIFactory;
}
注:TString定义如下
#ifdef UNICODE
#define TString std::wstring
#else
#define TString std::string
#endif
如果需要更换数据为 Access,只需要将“IFactory* poIFactory = new CFactoryfromMysql();”
改为“IFactory* poIFactory = new CFactoryfromAccess();”即可实现数据库的更换。
此时,问题来了。如果要在数据库增加一张表,用来存放公司部门信息,并对部门信息对象进行操作,部门对象也用员工对象定义类似的方法定义如下。
class IDepartment
{
public:
~IDepartment() {} virtual bool InserttoDB(Department& stDepartment) = 0;
virtual Department GetDepartment(int nID) = 0;
}; class CDepartmentfromMysql : public IDepartment
{
public:
bool InserttoDB(Department& stDepartment)
{
_tprintf(_T("Insert Department %s into mysql\n"), stDepartment.tstrDepartmentName.c_str());
return true;
} Department GetDepartment(int nID)
{
Department stDepartment;
printf("Get an Department from mysql by id %d\n", nID);
return stDepartment;
}
}; class CDepartmentfromAccess : public IDepartment
{
public:
bool InserttoDB(Department& stDepartment)
{
_tprintf(_T("Insert Department %s into access\n"), stDepartment.tstrDepartmentName.c_str());
return true;
} Department GetDepartment(int nID)
{
Department stDepartment;
printf("Get an Department from access by id %d\n", nID);
return stDepartment;
}
};
此时,如果仍使用工厂方法模式来处理,则可能会增加如下一行代码,来生产部门对象。
IDepartmentFactory* poIDepartmentFactoryFactory = new CDepartmentFactoryfromMysql();
如果采用的是简单工厂模式,由于要根据需要返回 IEmployee 和 IDepartment 2种对象,一个简单工厂已完全无法满足需求了,二个简单工厂(一个生产 IEmployee 对象,另一个生产 IDepartment 对象)则会发现一种数据库的操作都需要2个工厂类对象来处理,就像是想买苹果的手机需要找苹果公司去买,但买苹果的平板,却告知要到富士康公司去买了,已经失去简单工厂的本质意义了,也就是说简单工厂在此种情况下已经完全不能适应时代发展的需要了。工厂方法模式也有类似问题,如果需要更换数据库,需改更改2个工厂对象的用户代码,如果数据库中还要增加更多类型的信息操作,那么还需要增加更多的工厂对象,改动将越来越庞大。此时,该抽象工厂模式来拯救世界了,而且,实际上工厂方法模式早已为这一天准备了很久很久.....
2、抽象工厂模式拯救世界
2.1 抽象工厂模式的实现
class IFactory
{
public:
~IFactory() {} virtual IEmployee* CreateEmployee() = 0;
virtual IDepartment* CreateDepartment() = 0;
}; class CFactoryfromMysql : public IFactory
{
public:
IEmployee* CreateEmployee()
{
return new CEmployeefromMysql();
} IDepartment* CreateDepartment()
{
return new CDepartmentfromMysql();
}
}; class CFactoryfromAccess : public IFactory
{
public:
IEmployee* CreateEmployee()
{
return new CEmployeefromAccess();
} IDepartment* CreateDepartment()
{
return new CDepartmentfromAccess();
}
};
抽象工厂模式拯救世界的方式很简单,就是在抽象工厂早已准备好的工厂类接口 IFactory 中再小小的增加一个返回 IDepartment 部门对象的接口,然后所有的数据库工厂类中再实现生产 IDepartment 部门对象接口。
2.2 抽象工厂模式使用示例
void Test()
{
IFactory* poIFactory = new CFactoryfromMysql();
IEmployee* poIEmployee = NULL; if (!poIFactory)
{
return;
} poIEmployee = poIFactory->CreateEmployee(); if (poIEmployee)
{
Employee stEmployee; stEmployee.nID = 1;
stEmployee.tstrName = _T("Jim");
poIEmployee->InserttoDB(stEmployee);
delete poIEmployee;
} IDepartment* poIDepartment = poIFactory->CreateDepartment(); if (poIDepartment)
{
Department stDepartment; stDepartment.nID = 2;
stDepartment.tstrDepartmentName = _T("Marketing");
stDepartment.tstrManager = _T("Jim");
poIDepartment->InserttoDB(stDepartment);
delete poIDepartment;
}
delete poIFactory;
}
基本员工对象的部分不用变化,再增加部门对象的的代码即可,如果需要更换数据库,则只需要改动“IFactory*poIFactory = new CFactoryfromMysql();”一处即可。
抽象工厂模式解决了不论用户要买 iphone 还是要买 ipad,都只需要找苹果公司就可以了,如果要买小米或者小米平板,则统统找小米公司即可,工厂方法模式是一个工厂只生产一种产品,但当公司壮大升级为集团公司时,则一个公司可能会生产N种产品,那么此时需要抽象工厂模式来拯救公司的未来了。
世界安静片刻后,问题依然存在,尽管抽象工厂模式很牛X,但依然没有解决简单工厂模式和工厂方法模式遗留下来的问题——违背开放封闭原则,《大话设计模式》一书中最终给出了解决方案——采用反射,但反射这么高大上的东东在C++中是不存在的。C++是否真的就无法给出一个圆满的答案?是否最终拯救世界的重任还需C#来完成?欲知后事如何,请听下回分解。。。。。。
大话设计模式C++版——抽象工厂模式的更多相关文章
- 大话设计模式C++版——简单工厂模式
简单工厂模式应该是所有设计模式中最简单,也最基础的一种模式,以下是一个简单的采用工厂模式写一个加减法的计算器. 1.抽象接口类——依赖倒转原则(高层和底层都要依赖于抽象,针对接口编程) class I ...
- 大话设计模式Python实现- 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类 下面是一个抽象工厂的demo: #!/usr/bin/env pyth ...
- JAVA常用设计模式(一、抽象工厂模式)
抽象工厂模式 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最 ...
- 设计模式学习心得<抽象工厂模式 Abstract Factory>
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...
- C#设计模式系列:抽象工厂模式(AbstractFactory)
出自:http://www.cnblogs.com/libingql/archive/2012/12/09/2809754.html 1. 抽象工厂模式简介 1.1 定义 抽象工厂(Abstract ...
- [Python编程实战] 第一章 python的创建型设计模式1.1抽象工厂模式
注:关乎对象的创建方式的设计模式就是“创建型设计模式”(creational design pattern) 1.1 抽象工厂模式 “抽象工厂模式”(Abstract Factory Pattern) ...
- IOS设计模式浅析之抽象工厂模式(Abstract Factory)
概述 在前面两章中,分别介绍了简单工厂模式和工厂方法模式,我们知道简单工厂模式的优点是去除了客户端与具体产品的依赖,缺点是违反了“开放-关闭原则”:工厂方法模式克服了简单工厂模式的缺点,将产品的创建工 ...
- 【java设计模式】-03抽象工厂模式
抽象工厂 简述 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类.在抽象工厂模式中,接口是负责创建一个相关对象的工厂 ...
- 一天一个设计模式——Abstract Factory抽象工厂模式
一.模式说明 前面学习了工厂方法(Factory Method)模式.在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理.这里学习的抽象工厂 ...
随机推荐
- 【转】从MVC到前后端分离
1. 理解MVC MVC是一种经典的设计模式,全名为Model-View-Controller,即模型-视图-控制器. 其中,模型是用于封装数据的载体,例如,在Java中一般通过一个简单的POJO(P ...
- [Cordova] 无法编译Visual Studio项目里Plugin副本的Native Code
[Cordova] 无法编译Visual Studio项目里Plugin副本的Native Code 问题情景 开发Cordova Plugin的时候,开发的流程应该是: 建立Cordova Plug ...
- 【精心推荐】几款极好的 JavaScript 文件上传插件
文件上传功能作为网页重要的组成部分,几乎无处不在,从简单的单个文件上传到复杂的批量上传.拖放上传,需要开发者花费大量的时间和精力去处理,以期实现好用的上传功能.这篇文章向大家推荐几款很棒的 JavaS ...
- [deviceone开发]-HeaderView和FooterView的示例
一.简介 这个是利用do_ListView组件实现下拉和上拉刷新功能的例子,除了do_ListView,其它比如do_Webview,do_ScrollView都有这个个功能.对应的BBS里的帖子详细 ...
- CSS的简介
CSS(Cascading Style Sheets):层叠样式表 层叠:一层一层的 样式表:有很多的属性和属性值 css将网页内容和显示样式进行分离,提高了显示功能 CSS通常被称为CSS样式表或层 ...
- Web安全之点击劫持(ClickJacking)
点击劫持(ClickJacking)是一种视觉上的欺骗手段.大概有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的 ...
- 百度在线编辑器UEditor(v1.3.6) .net环境下详细配置教程
UEditor是百度开发团队奉献的一款很不错的在线编辑器.在百度自己很多产品上都有应用,本文主要是该编辑器的配置教程. 1.下载UEditor,当前最新版本是1.3.6.这里下载的.net版本,选择U ...
- Android+PHP服务器+MySQL实现安卓端的登录
时隔已久的一个任务,今天终于可以画上一个句号了.心情是万分的激动,虽然这份小成就来的有点迟但还是按捺不住心情的澎湃.下面我就先上几张图片来展示一下我的成绩 android源代码: 首先最重要的一件事是 ...
- Android对话框
这周过的实在是艰辛,自打这周二起我的本本就开始闹"罢工",最后还是重装系统了事. . . 只是可怜了我的那些被格了的软件(悲伤辣么大)! 往事不要再提,人生几度风雨... 简 ...
- Android微信登陆
前言 分享到微信朋友圈的功能早已经有了,但微信登录推出并不久,文档写的也并不是很清楚,这里记录分享一下. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.co ...