23种设计模式(八)对象创建之抽象工厂
本系列所有文章来自李建忠老师的设计模式笔记,系列如下:
设计模式(一)面向对象设计原则
23种设计模式(二)组件协作之模板方法
23种设计模式(三)组件协作之策略模式
23种设计模式(四)组件协作之观察者模式
23种设计模式(五)单一职责之装饰模式
23种设计模式(六)单一职责之桥模式
23种设计模式(七)对象创建之工厂方法
23种设计模式(八)对象创建之抽象工厂
23种设计模式(九)对象创建之原型模式
23种设计模式(十)对象创建之构建器
23种设计模式(十一)对象性能之单件模式
23种设计模式(十二)对象性能之享元模式
23种设计模式(十三)接口隔离之门面模式
23种设计模式(十四)接口隔离之代理模式
23种设计模式(十五)接口隔离之适配器
23种设计模式(十六)接口隔离之中介者
23种设计模式(十七)状态变化之状态模式
23种设计模式(十八)状态变化之备忘录
23种设计模式(十九)数据结构之组合模式
23种设计模式(二十)数据结构之迭代器
23种设计模式(二十一)数据结构之职责链
23种设计模式(二十二)行为变化之命令模式
23种设计模式(二十三)行为变化之访问器
23种设计模式(二十四)领域规则之解析器
文章目录
- 动机
- 设计方法一
- 设计方法二
- 设计方法三
- 模式定义
- 要点总结
抽象工厂与工厂方法极其类似,都是绕开new
的,但是有些许不同。
动机
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
假设现在有这样一个需求,我们需要做一个数据访问层。
设计方法一
在数据访问层需要创建一系列的对象,比如建立链接,创建数据库的命令对象,创建数据库的DataReader
对象。但是数据库可能不只有Sql
的,可能还有别的类型的。
- EmployeeDAO1.cpp
class EmployeeDAO{public:vector<EmployeeDO> GetEmployees(){SqlConnection* connection =new SqlConnection();connection->ConnectionString = "...";SqlCommand* command =new SqlCommand();command->CommandText="...";command->SetConnection(connection);SqlDataReader* reader = command->ExecuteReader();while (reader->Read()){}}
};
那么上述这种实现就不支持多种数据库的方法。
设计方法二
如果要支持多种数据库,第一种反应就是实现面向接口的编程。基于上一节的工厂方法,为每一个类实现一个工厂
- EmployeeDAO2.cpp
//数据库访问有关的基类
class IDBConnection{};
class IDBConnectionFactory{public:virtual IDBConnection* CreateDBConnection()=0;
};class IDBCommand{};
class IDBCommandFactory{public:virtual IDBCommand* CreateDBCommand()=0;
};class IDataReader{};
class IDataReaderFactory{public:virtual IDataReader* CreateDataReader()=0;
};//支持SQL Server
class SqlConnection: public IDBConnection{};
class SqlConnectionFactory:public IDBConnectionFactory{};class SqlCommand: public IDBCommand{};
class SqlCommandFactory:public IDBCommandFactory{};class SqlDataReader: public IDataReader{};
class SqlDataReaderFactory:public IDataReaderFactory{};//支持Oracle
class OracleConnection: public IDBConnection{};class OracleCommand: public IDBCommand{};class OracleDataReader: public IDataReader{};class EmployeeDAO{// 三个工厂创建三个对象IDBConnectionFactory* dbConnectionFactory;IDBCommandFactory* dbCommandFactory;IDataReaderFactory* dataReaderFactory;public:vector<EmployeeDO> GetEmployees(){// 多态实现IDBConnection* connection =dbConnectionFactory->CreateDBConnection();connection->ConnectionString("...");IDBCommand* command =dbCommandFactory->CreateDBCommand();command->CommandText("...");command->SetConnection(connection); //关联性IDBDataReader* reader = command->ExecuteReader(); //关联性while (reader->Read()){}}
};
上述方法确实能够解决new
的问题,但是也存在一些其它的问题。就是一开始创建的三个工厂必须是同系列的,具备关联性。解决这个问题就需要引入抽象工厂。
设计方法三
如果将一开始创建的三个工厂放在一个类里面,就不会存在这个问题。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?
- EmployeeDAO3.cpp
//数据库访问有关的基类
class IDBConnection{};class IDBCommand{};class IDataReader{};class IDBFactory{public:virtual IDBConnection* CreateDBConnection()=0;virtual IDBCommand* CreateDBCommand()=0;virtual IDataReader* CreateDataReader()=0;};//支持SQL Server
class SqlConnection: public IDBConnection{};
class SqlCommand: public IDBCommand{};
class SqlDataReader: public IDataReader{};class SqlDBFactory:public IDBFactory{public:virtual IDBConnection* CreateDBConnection()=0;virtual IDBCommand* CreateDBCommand()=0;virtual IDataReader* CreateDataReader()=0;};//支持Oracle
class OracleConnection: public IDBConnection{};class OracleCommand: public IDBCommand{};class OracleDataReader: public IDataReader{};class EmployeeDAO{IDBFactory* dbFactory;public:vector<EmployeeDO> GetEmployees(){IDBConnection* connection =dbFactory->CreateDBConnection();connection->ConnectionString("...");IDBCommand* command =dbFactory->CreateDBCommand();command->CommandText("...");command->SetConnection(connection); //关联性IDBDataReader* reader = command->ExecuteReader(); //关联性while (reader->Read()){}}
};
模式定义
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
要点总结
如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
“系列对象”指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。(因为如果要加新对象的话,就会改变抽象基类IDBFactory
)
23种设计模式(八)对象创建之抽象工厂相关推荐
- 23种设计模式(3):抽象工厂模式
定义:为创建一组相关或相互依赖的对象提供一个接口,并且无需指定他们的详细类. 类型:创建类模式 类图: 抽象工厂模式与工厂方法模式的差别 抽象工厂模式是工厂方法模式的升级版本号,他用来创建一组相关或者 ...
- 设计模式(十)------23种设计模式(3):抽象工厂模式
转载自:https://www.cnblogs.com/chenpi/p/5156801.html (风一样的码农) 阅读目录 使用频率:★★★★★ 一.什么是抽象工厂模式 二.补充说明 三.角色 四 ...
- 23种设计模式----原型模式----创建型模式
原型模式 1.1什么是原型模式 1.2为什么要使用原型模式 2.原型模式的解释 3.例子 3.1例子将要实现的目标 3.2例子设计 3.3原型类 3.4具体实现的3个原型实例类 3.5管理类 3.6工 ...
- 设计模式(20):创建型-抽象工厂模式(Abstract Factory)
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 23种设计模式应用场景
23种设计模式应用场景 创建型模式 工厂方法模式: 原型模式:clone/fork子线程 建造者模式:框架组件实例化 抽象工厂模式:业务+反射 单例模式:只读单实例场景 结构型模式 装饰模式:换装软件 ...
- (原创)23种设计模式一网打尽,看这篇就够了!
设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.建造者模式.单例模式.原型模式. 结构型模式,共七种:适配器模式.代理模式.装饰器模式.桥接模式.组合模式 ...
- 23种设计模式之模板方法
23种设计模式总篇:chenmingyu.top/design/ 模板方法 模板方法属于行为型模式 定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重定 ...
- 快来,这里有23种设计模式的Go语言实现
摘要:设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结,使用设计模式是为了可重用代码.让代码更容易被他人理解并且保证代码可靠性. 本文分享自华 ...
- Java的7大设计原则和23种设计模式
目录 一.UML类图 二. 设计原则 1.单一职责原则 2.里氏替换原则 3.依赖倒置原则 4.接口隔离原则 5.迪米特法则-最少知道原则 6.开闭原则 7.组合/聚合复用原则 三.Java中的23 ...
- 23种设计模式通俗理解
23种设计模式通俗理解 1.根据目的来分 2.根据作用范围来分 3.GoF的23种设计模式的功能 1.FACTORY 工厂方法 2.BUILDER建造者模式 3.FACTORY METHOD抽象工厂 ...
最新文章
- MD5 - Bump Mapping
- ThinkPHP的访问模式分为四种模式
- 015-图片文件上传
- linux设置环境变量_什么是linux环境变量
- 本地修改指向服务器,本地修改指向服务器
- drupal mysql_Drupal MySQL查询优化
- fedora 忘记root密码
- 淘宝H5移动端解决方案
- Given a list,rotate the list to right by k places, where k is nonegative.
- 用Python实现排序算法——快速排序
- 听力技巧-真题代练及填空题
- 肯普纳级数收敛性的证明
- 求10000以内n的阶乘(openjudge 2923)
- java 接口编程iservices_java – 通用接口
- html代码不安全,安全 – HTML编码是否会阻止各种XSS攻击?
- 0001-【linux系统】-用于生物信息分析该如何安装ubuntu系统?
- mplayer用法大全
- OpenCV 3.0 高动态范围图像
- MySQL中文存到数据库是,springMVC保存数据到mysql数据库中文乱码问题解决方法
- 掌中革命--手机富媒体
热门文章
- OpenCV python Calibration
- PTA是什么?BT-WIFI共存 转帖
- AjaxUpload
- 华为系列设备优先级总结(三)
- Linux之scsi网络存储
- 2019.5.25 Noip模拟测试2 T1题解
- 一键环境安装包无法修改网站目录提示.user.ini权限问题解决方法
- 如何获取系统Home(Launcher)应用判断用户是否处于home界面
- Sublime Text2.0.2注册码,添加python编译系统:
- Linux C语言解析并显示.bmp格式图片