本系列所有文章来自李建忠老师的设计模式笔记,系列如下:
设计模式(一)面向对象设计原则
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种设计模式(八)对象创建之抽象工厂相关推荐

  1. 23种设计模式(3):抽象工厂模式

    定义:为创建一组相关或相互依赖的对象提供一个接口,并且无需指定他们的详细类. 类型:创建类模式 类图: 抽象工厂模式与工厂方法模式的差别 抽象工厂模式是工厂方法模式的升级版本号,他用来创建一组相关或者 ...

  2. 设计模式(十)------23种设计模式(3):抽象工厂模式

    转载自:https://www.cnblogs.com/chenpi/p/5156801.html (风一样的码农) 阅读目录 使用频率:★★★★★ 一.什么是抽象工厂模式 二.补充说明 三.角色 四 ...

  3. 23种设计模式----原型模式----创建型模式

    原型模式 1.1什么是原型模式 1.2为什么要使用原型模式 2.原型模式的解释 3.例子 3.1例子将要实现的目标 3.2例子设计 3.3原型类 3.4具体实现的3个原型实例类 3.5管理类 3.6工 ...

  4. 设计模式(20):创建型-抽象工厂模式(Abstract Factory)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  5. 23种设计模式应用场景

    23种设计模式应用场景 创建型模式 工厂方法模式: 原型模式:clone/fork子线程 建造者模式:框架组件实例化 抽象工厂模式:业务+反射 单例模式:只读单实例场景 结构型模式 装饰模式:换装软件 ...

  6. (原创)23种设计模式一网打尽,看这篇就够了!

    设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.建造者模式.单例模式.原型模式. 结构型模式,共七种:适配器模式.代理模式.装饰器模式.桥接模式.组合模式 ...

  7. 23种设计模式之模板方法

    23种设计模式总篇:chenmingyu.top/design/ 模板方法 模板方法属于行为型模式 定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重定 ...

  8. 快来,这里有23种设计模式的Go语言实现

    摘要:设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结,使用设计模式是为了可重用代码.让代码更容易被他人理解并且保证代码可靠性. 本文分享自华 ...

  9. Java的7大设计原则和23种设计模式

    目录 一.UML类图 二. 设计原则 1.单一职责原则 2.里氏替换原则 3.依赖倒置原则 4.接口隔离原则 5.迪米特法则-最少知道原则 6.开闭原则 7.组合/聚合复用原则 三.Java中的23 ...

  10. 23种设计模式通俗理解

    23种设计模式通俗理解 1.根据目的来分 2.根据作用范围来分 3.GoF的23种设计模式的功能 1.FACTORY 工厂方法 2.BUILDER建造者模式 3.FACTORY METHOD抽象工厂 ...

最新文章

  1. MD5 - Bump Mapping
  2. ThinkPHP的访问模式分为四种模式
  3. 015-图片文件上传
  4. linux设置环境变量_什么是linux环境变量
  5. 本地修改指向服务器,本地修改指向服务器
  6. drupal mysql_Drupal MySQL查询优化
  7. fedora 忘记root密码
  8. 淘宝H5移动端解决方案
  9. Given a list,rotate the list to right by k places, where k is nonegative.
  10. 用Python实现排序算法——快速排序
  11. 听力技巧-真题代练及填空题
  12. 肯普纳级数收敛性的证明
  13. 求10000以内n的阶乘(openjudge 2923)
  14. java 接口编程iservices_java – 通用接口
  15. html代码不安全,安全 – HTML编码是否会阻止各种XSS攻击?
  16. 0001-【linux系统】-用于生物信息分析该如何安装ubuntu系统?
  17. mplayer用法大全
  18. OpenCV 3.0 高动态范围图像
  19. MySQL中文存到数据库是,springMVC保存数据到mysql数据库中文乱码问题解决方法
  20. 掌中革命--手机富媒体

热门文章

  1. OpenCV python Calibration
  2. PTA是什么?BT-WIFI共存 转帖
  3. AjaxUpload
  4. 华为系列设备优先级总结(三)
  5. Linux之scsi网络存储
  6. 2019.5.25 Noip模拟测试2 T1题解
  7. 一键环境安装包无法修改网站目录提示.user.ini权限问题解决方法
  8. 如何获取系统Home(Launcher)应用判断用户是否处于home界面
  9. Sublime Text2.0.2注册码,添加python编译系统:
  10. Linux C语言解析并显示.bmp格式图片