GOF:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  类图:

  


  

  观察类图,关键就在于左边,即AbstractFactory和它的两个子类。想要理解这个模式,我们可以真的将它看作一个工厂。对于生产家电的工厂,一般要生产电视和洗衣机,但是在美国的家电工厂生产的是等离子电视和全自动洗衣机,在非洲的家电工厂生产的是CRT彩电和半自动洗衣机。把这个例子转换成类似上面的类图就如下:

  这时,如果想要开工厂,就能从彩电工厂生产标准知道彩电工厂能生产电视和洗衣机,然后根据你在哪个国家来具体决定彩电工厂的类型。

  AbstractFactory一般是抽象类(但不是绝对的),它定义了必需的接口,而具体接口的实现放到了子类。用户只需知道Factory中有什么接口就行了,剩下就交给多态吧(在设计模式中,很多巧妙的地方就是靠多态实现的)。

  比如:一群学生要去参观家电工厂的生产过程,则代码如下:

  1. void StudentVisit(AbstractFactory& factory) {
  2. factory.MakeTV();
  3. factory.MakeWasher();
  4. }
  5.  
  6. int main() {
  7. USAFactory factory;
  8. StudentVisit(factory);
  9.  
  10. ;
  11. }

  这里实际传入的参数是美国家电工厂,则实际调用的是美国家电工厂的MakeTV()和MakeWasher()。

  适用性:

  • 一个系统要独立于它的产品的创建,组合和表示时。(我们只需要知道有什么接口,而不需要了解子类是怎么实现的)
  • 一个系统要由多个产品系列中的一个来配置时。(比如上面电视有多种,但是美国彩电工厂要的是等离子电视)
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。(彩电工厂需要生产电视和洗衣机,这两个就是相关的产品)
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。(我们只需要调用抽象类的接口,而不需要到子类中看具体的方法)

  优点 + 缺点:

  • 它分离了具体的类。
  • 它使得易于交换产品系列。改变使用的具体工厂就能生产不同的产品。
  • 它有利于产品的一致性。每一个具体工厂生产的都是同一等级的产品。
  • 难以支持新种类的产品。如果要在抽象类中增加接口,每个具体工厂都要进行修改。

 


  最后以一个创建游戏场景的例子结束,该游戏场景会产生地形,光源,植被。

  类图:

  代码:

  先看看Product,即类图右边的类:

  地形类:

  1. class Terrain {
  2. public:
  3. ;
  4. };
  5.  
  6. class DesertTerrain : public Terrain {
  7. public:
  8. DesertTerrain() {
  9. m_type = "Desert";
  10. }
  11. string GetType() const {
  12. return m_type;
  13. }
  14. private:
  15. string m_type;
  16. };
  17.  
  18. class MountainTerrain : public Terrain {
  19. public:
  20. MountainTerrain() {
  21. m_type = "Mountain";
  22. }
  23. string GetType() const {
  24. return m_type;
  25. }
  26. private:
  27. string m_type;
  28. };

  光源类:

  1. class Light {
  2. public:
  3. ;
  4. };
  5.  
  6. class SpotLight : public Light{
  7. public:
  8. SpotLight() {
  9. m_type = "Spot Light";
  10. }
  11. string GetType() const {
  12. return m_type;
  13. }
  14. private:
  15. string m_type;
  16. };
  17.  
  18. class DirectionLight : public Light {
  19. public:
  20. DirectionLight() {
  21. m_type = "Direction Light";
  22. }
  23. string GetType() const {
  24. return m_type;
  25. }
  26. private:
  27. string m_type;
  28. };

  植被类:

  1. class Plant {
  2. public:
  3. ;
  4. };
  5.  
  6. class TreePlant : public Plant {
  7. public:
  8. TreePlant() {
  9. m_type = "Tree";
  10. }
  11. string GetType() const {
  12. return m_type;
  13. }
  14. private:
  15. string m_type;
  16. };
  17.  
  18. class CactusPlant : public Plant {
  19. public:
  20. CactusPlant() {
  21. m_type = "Cactus";
  22. }
  23. string GetType() const {
  24. return m_type;
  25. }
  26. private:
  27. string m_type;
  28. };

  

 以下就看工厂类:

  1. class GameSceneFactory {
  2. public:
  3.  
  4. ;
  5. ;
  6. ;
  7. };
  8.  
  9. class DesertSceneFactory : public GameSceneFactory {
  10. public:
  11.  
  12. Terrain* MakeTerrain() const {
  13. return new DesertTerrain();
  14. }
  15.  
  16. Light* MakeLight() const {
  17. return new DirectionLight();
  18. }
  19.  
  20. Plant* MakePlant() const {
  21. return new CactusPlant();
  22. }
  23. };
  24.  
  25. class MountainSceneFactory : public GameSceneFactory {
  26. public:
  27.  
  28. Terrain* MakeTerrain() const {
  29. return new MountainTerrain();
  30. }
  31.  
  32. Light* MakeLight() const {
  33. return new SpotLight();
  34. }
  35.  
  36. Plant* MakePlant() const {
  37. return new TreePlant();
  38. }
  39. };

  以下就是具体的使用:

  1. class Game {
  2. public:
  3. void createScene(GameSceneFactory& factory) {
  4. m_terrain = factory.MakeTerrain();
  5. m_light = factory.MakeLight();
  6. m_plant = factory.MakePlant();
  7. print();
  8. }
  9. void print() {
  10. cout << "------Game Scene------" << endl;
  11. cout << "Terrain: " << m_terrain->GetType() << endl;
  12. cout << "Light: " << m_light->GetType() << endl;
  13. cout << "Plant: " << m_plant->GetType() << endl;
  14. }
  15. private:
  16. Terrain* m_terrain;
  17. Light* m_light;
  18. Plant* m_plant;
  19. };
  20.  
  21. int main() {
  22. Game game;
  23. MountainSceneFactory factory;
  24. game.createScene(factory);
  25. }

  结果:


  小结:抽象工厂模式是一个比较常用的模式,需要好好掌握。利用真实生活中的工厂就比较好理解该模式的运作,但真正要掌握还得在日常编码中的适当场合使用。

  

抽象工厂模式(Abstract Factory)的更多相关文章

  1. .NET设计模式(2):1.2 抽象工厂模式(Abstract Factory)

    概述 抽象工厂模式(Abstract Factory)是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口 ...

  2. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...

  3. 【设计模式】抽象工厂模式 Abstract Factory Pattern

    简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...

  4. 设计模式 - 抽象工厂模式(abstract factory pattern) 具体解释

    抽象工厂模式(abstract factory pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/2709 ...

  5. 抽象工厂模式(Abstract Factory)C#实例

    抽象工厂模式(Abstract Factory)C#实例 本文出处http://www.dofactory.com/net/abstract-factory-design-pattern 一.场景描述 ...

  6. 二十四种设计模式:抽象工厂模式(Abstract Factory Pattern)

    抽象工厂模式(Abstract Factory Pattern) 介绍提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例有Message和MessageModel,Messag ...

  7. 【UE4 设计模式】抽象工厂模式 Abstract Factory Pattern

    概述 描述 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类:具体的工厂负责实现具体的产品实例 抽象工厂中每个工厂可以创建多种产品(如苹果公司生产iPhone.iPad): 工厂方法 ...

  8. Net设计模式实例之抽象工厂模式(Abstract Factory Pattern)

    一.抽象工厂模式简介(Bref Introduction) 抽象工厂模式(Abstract Factory Pattern),提供一个创建一系列相关或者相互依赖对象的接口,而无需制定他们的具体类.优点 ...

  9. C#设计模式——抽象工厂模式(Abstract Factory Pattern)

    一.概述在软件开发中,常常会需要创建一系列相互依赖的对象,同时,由于需求的变化,往往存在较多系列对象的创建工作.如果采用常规的创建方法(new),会造成客户程序和对象创建工作的紧耦合.对此,抽象工厂模 ...

  10. Objective-C设计模式——抽象工厂模式Abstract Factory(对象创建)

    抽象工厂模式 理解了工厂方法模式,其实抽象工厂和工厂方法模式有很多的相似之处.抽象工厂同样是分离客户端对象的创建和逻辑代码的,但是抽象工厂往往是产生一组数据而不单单是产生一个产品. 抽象工厂提供一个创 ...

随机推荐

  1. RDLC的部署(无法找到Microsoft.ReportViewer.ProcessingObjectModel.dll文件)

    CMD命令:C:\Windows\assembly\GAC_MSIL\ rdlc 相比微软的其他产品来说,做得还真是够烂的了,比水晶报表也烂得多. 但不知为何我还是宁可先择 rdlc.并且渐渐上手了. ...

  2. [xsd学习]xsd介绍

    一直以来项目中对xml格式的判断使用的都是dtd格式,直到最近才发现,不知何时都已经转为xsd来进行判断和校验,于是今天专门找资料看下,不得不说,对于这类资料的入门,w3cschool真是个不错的资料 ...

  3. Apache ActiveMQの版本更迭和Apache ActiveMQの故障转移

    本文描述apache activemq 版本更迭的原因以及Apache ActiveMQのThe Failover Transport new features in 5.2.0  1.对信息的传输/ ...

  4. 【Oracle】表空间容量修改

    -- 查看表空间容量 SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", ...

  5. ccc prefab

    MonsterPrefab.js var Helpers = require('Helpers'); cc.Class({ extends: cc.Component, properties: { s ...

  6. Storm实战:在云上搭建大规模实时数据流处理系统(Storm+Kafka)

    在大数据时代,数据规模变得越来越大.由于数据的增长速度和非结构化的特性,常用的软硬件工具已无法在用户可容忍的时间内对数据进行采集.管理和处理.本文主要介绍如何在阿里云上使用Kafka和Storm搭建大 ...

  7. gulp + webpack 构建多页面前端项目

    修改增加了demo地址 gulp-webpack-demo 之前在使用gulp和webpack对项目进行构建的时候遇到了一些问题,最终算是搭建了一套比较完整的解决方案,接下来这篇文章以一个实际项目为例 ...

  8. sqlite 数据类型 全面

    http://blog.csdn.net/jin868/article/details/5961263 一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断.SQ ...

  9. Codeforces Round #252 (Div. 2) B. Valera and Fruits

    #include <iostream> #include <vector> #include <algorithm> #include <map> us ...

  10. 洛谷 P1198 [JSOI2008]最大数 Label:线段树

    题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度. 2. 插入操作 ...