前面说过,简单工厂模式是最基础的一种设计模式,那以工厂命名的设计模式就是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++版——抽象工厂模式的更多相关文章

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

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

  2. 大话设计模式Python实现- 抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类 下面是一个抽象工厂的demo: #!/usr/bin/env pyth ...

  3. JAVA常用设计模式(一、抽象工厂模式)

    抽象工厂模式 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最 ...

  4. 设计模式学习心得<抽象工厂模式 Abstract Factory>

    抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...

  5. C#设计模式系列:抽象工厂模式(AbstractFactory)

    出自:http://www.cnblogs.com/libingql/archive/2012/12/09/2809754.html 1. 抽象工厂模式简介 1.1 定义 抽象工厂(Abstract ...

  6. [Python编程实战] 第一章 python的创建型设计模式1.1抽象工厂模式

    注:关乎对象的创建方式的设计模式就是“创建型设计模式”(creational design pattern) 1.1 抽象工厂模式 “抽象工厂模式”(Abstract Factory Pattern) ...

  7. IOS设计模式浅析之抽象工厂模式(Abstract Factory)

    概述 在前面两章中,分别介绍了简单工厂模式和工厂方法模式,我们知道简单工厂模式的优点是去除了客户端与具体产品的依赖,缺点是违反了“开放-关闭原则”:工厂方法模式克服了简单工厂模式的缺点,将产品的创建工 ...

  8. 【java设计模式】-03抽象工厂模式

    抽象工厂 简述 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类.在抽象工厂模式中,接口是负责创建一个相关对象的工厂 ...

  9. 一天一个设计模式——Abstract Factory抽象工厂模式

    一.模式说明 前面学习了工厂方法(Factory Method)模式.在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理.这里学习的抽象工厂 ...

随机推荐

  1. 【javascript激增的思考03】MVVM与Knockout

    前言 今天搞的有点快,因为上午简单研究了下MVC,发现MVC不太适合前端开发,然后之前看几位前端前辈都推荐前端使用MVVM,但是我对其还不甚了解,所以我觉得下午还是应该先看看他是神马先,后面再决定要不 ...

  2. Apache 配置屏蔽某些请求头

    Apache配置文件代码.xwamp:Windows下搭建Apache + PHP + MySQL环境 <Location /> SetEnvIfNoCase User-Agent &qu ...

  3. 2034-人见人爱A-B(c++实现)

    Problem Description 参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的差,就是做集合的减法 ...

  4. ios8版本地图定位注意点

    学习ios地图定位 我先定义一个属性: @property (weak, nonatomic) IBOutlet MKMapView *mapV; 然后在项目运行时初始化该属性一些参数: //设置地图 ...

  5. 【网络编程】Socket概念及简单聊天…

    Socket(套接字) * Socket就是为网络服务提供的一种机制 * 通信的两端都是Socket * 网络通信其实就是Socket间的通信 * 数据在两个Socket间通过IO传输 我们来看看下面 ...

  6. 不用画线 设置UITableView的全屏分隔线

    如图  添加如下代码 sTableView.separatorInset = UIEdgeInsetsZero; sTableView.layoutMargins = UIEdgeInsetsZero ...

  7. 软件测试人员必备Linux命令(初、中、高级)

    有些技能可以事半功倍,有些命运掌握在我们手中.熟练的掌握和使用这些命令可以提高工作效率,并且结合这些命令对测试过程中遇到的问题进行一些初步的定位. 1 目录与文件操作1.1 ls(初级)使用权限:所有 ...

  8. Html5 dataset--自定义属性

    dataset--自定义属性 HTMLElement.dataset data-*属性集 元素上保存数据 <div id="user" data-id="12345 ...

  9. @在php中的作用

    @是PHP提供的错误信息屏蔽的专用符号. 使用@mysql_query 不会出现Warning,而原来mysql_query 在遇到错误时会在页面上访提示Warning. 看PHP的代码,总有些行前边 ...

  10. Cygwin VS MinGW

    首先MingW和cygwin都可以用来跨平台开发.  MinGW是Minimalistic GNU for Windows的缩写,也就是Win版的GCC.  Cygwin则是全面模拟了Linux的接口 ...