常规的对象创建方法:

  1. //创建一个Road对象
  2. Road road =new Road();

new 的问题:

实现依赖,不能应对“具体实例化类型”的变化。
解决思路:
    封装变化点-----哪里变化,封装哪里
    潜台词: 如果没有变化,当然不需要额外的封装!

工厂模式的缘起
    变化点在“对象创建”,因此就封装“对象创建”
    面向接口编程----依赖接口,而非依赖实现
最简单的解决方法:

  1. class RoadFactory
    {
  2.    public static Road CreateRoad()
  3.   {
  4.    return new Road();
  5.   }
  6. }

  7. //创建一个Road对象
    Road road=roadFactory.CreateRoad();

创建一系列相互依赖对象的创建工作:
假设一个游戏开场景:
我们需要构造"道路"、"房屋"、"地道","从林"...等等对象
工厂方法如下:

  1. class RoadFactory
  2. {
  3. public static Road CreateRoad()
  4. {
  5. return new Road();
  6. }
  7. public static Building CreateBuilding()
  8. {
  9. return new Building();
  10. }
  11. public static Tunnel CreateTunnel()
  12. {
  13. return new Tunnel();
  14. }
  15. public static Jungle CreateJungle()
  16. {
  17. return new Jungle();
  18. }
  19. }

调用方式如下:

  1. Road road = RoadFactory.CreateRoad();
  2. Building building = RoadFactory.CreateBuilding();
  3. Tunnel tunnel = RoadFactory.CreateTunnel();
  4. Jungle jungle = RoadFactory.CreateJungle();

如上可见简单工厂的问题:
    不能应对"不同系列对象"的变化。比如有不同风格的场景---对应不同风格的道路,房屋、地道....

如何解决:
    使用面向对象的技术来"封装"变化点。
动机(Motivate):
    在软件系统中,经常面临着"一系统相互依赖的对象"的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作。
    如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种"封装机制"来避免客户程序和这种"多系列具体对象创建工作"的紧耦合?

意图(Intent):
    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
                                                 ----《设计模式》GOF
结构图(Struct):
            

适用性:
    
1.一个系统要独立于它的产品的创建、组合和表示时。
    2.一个系统要由多个产品系统中的一个来配置时。
    3.当你要强调一系列相关的产品对象的设计以便进行联合使用时。
    4.当你提供一个产品类库,而只想显示它们的接口不是实现时。
生活例子:

               
结构图代码实现:

  1. public abstract class AbstractFactory
  2. {
  3. public abstract AbstractProductA CreateProductA();
  4.  
  5. public abstract AbstractProductB CreateProductB();
  6. }
  1. public class ConcreteFactory1 : AbstractFactory
  2. {
  3.  
  4. public override AbstractProductA CreateProductA()
  5. {
  6. return new ProductA1();
  7. }
  8.  
  9. public override AbstractProductB CreateProductB()
  10. {
  11. return new ProductB1();
  12. }
  13. }
  1.  
  1. public class ConcreteFactory2 : AbstractFactory
  2. {
  3.  
  4. public override AbstractProductA CreateProductA()
  5. {
  6. return new ProductA2();
  7. }
  8.  
  9. public override AbstractProductB CreateProductB()
  10. {
  11. return new ProductB2();
  12. }
  13. }
  1. public abstract class AbstractProductA
  2. {
  3. public abstract void Interact(AbstractProductB b);
  4. }
  1. public class ProductA1 : AbstractProductA
  2. {
  3. public override void Interact(AbstractProductB b)
  4. {
  5. Console.WriteLine(this.GetType().Name + "interact with " + b.GetType().Name);
  6. }
  7. }
  1.  
  1. public class ProductA2 : AbstractProductA
  2. {
  3. public override void Interact(AbstractProductB b)
  4. {
  5. Console.WriteLine(this.GetType().Name + "interact with " + b.GetType().Name);
  6. }
  7. }
  1. public abstract class AbstractProductB
  2. {
  3. public abstract void Interact(AbstractProductA a);
  4. }
  1. public class ProductB1 : AbstractProductB
  2. {
  3. public override void Interact(AbstractProductA a)
  4. {
  5. Console.WriteLine(this.GetType().Name + " interact with " + a.GetType().Name);
  6. }
  7. }
  1.  
  1. public class ProductB2 : AbstractProductB
  2. {
  3. public override void Interact(AbstractProductA a)
  4. {
  5. Console.WriteLine(this.GetType().Name + " interact with " + a.GetType().Name);
  6. }
  7. }

  1. public class Client
  2. {
  3. private AbstractProductA AbstractProductA;
  4. private AbstractProductB AbstractProductB;
  5.  
  6. public Client(AbstractFactory factory)
  7. {
  8. AbstractProductA = factory.CreateProductA();
  9. AbstractProductB = factory.CreateProductB();
  10. }
  11.  
  12. public void Run()
  13. {
  14. AbstractProductA.Interact(AbstractProductB);
  15. AbstractProductB.Interact(AbstractProductA);
  16. }
  17. }
  1. public static void Main()
  2. {
  3. // Abstractfactory1
  4. AbstractFactory factory1 = new ConcreteFactory1();
  5. Client c1 = new Client(factory1);
  6. c1.Run();
  7.  
  8. //Abstractfactory1
  9. AbstractFactory factory2 = new ConcreteFactory2();
  10. Client c2 = new Client(factory2);
  11. c2.Run();
  12. }
Abstract Factory注意的几点:
    如果不存在”多系列对象创建“的需求变化,则没必要应用Abstract Factory模式,静态工厂方法足矣。
    "系列对象"指的是这些对象之间有相互依赖、或作用的关系。例如游戏开发场景中的"道路"与"房屋"依赖,“道路”与“地道”的依赖。
Abstract Factory模式主要在于应对"新系列"的需求变动。其缺点在于难以应对”新对象“的需求变动。
Abstract Factory模式经常和Factory Method模式共同组合来应对“对象创建”的需求变化。

2.抽象工厂(Abstract Factory)的更多相关文章

  1. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  2. 面向对象设计——抽象工厂(Abstract Factory)模式

    定义 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类.抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么.这样一来,客户就能从具体的产 ...

  3. 设计模式——抽象工厂(Abstract Factory)

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类. ——DP UML类图 模式说明 抽象工厂与工厂方法在定义上最明显的区别是“创建一系列相关或相互依赖对象的接口”,由此可以看出抽象工 ...

  4. 5、抽象工厂 abstract factory 将关联组件组成产品 创建型模式

    趁热打铁,紧跟着上一节的工厂方法模式.这一节介绍一下抽象工厂模式,以及分析俩个模式的不同 1.何为抽象模式? 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他 ...

  5. 工厂模式[3] 抽象工厂 Abstract Factory

    简介 1.简单工厂,或静态工厂,产品接口 定义:专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类或实现同一接口 优点:客户端可以直接消费产品,而不必关心具体产品的实现(不关心对象的 ...

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

    简介 抽象工厂模式是创建型模式的一种, 与工厂方法不同的是抽象工厂针对的是生产一组相关的产品, 即一个产品族. 抽象工厂使用工厂方法模式来生产单一产品, 单一产品的具体实现分别属于不同的产品族. 抽象 ...

  7. C2:抽象工厂 Abstract Factory

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 应用场景: 一系列相互依赖的对象有不同的具体实现.提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合 UM ...

  8. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  9. 【设计模式】——抽象工厂Abstract Factory

    模式意图 提供对象的使用接口,隐藏对象的创建过程. 模式结构 AbstractFactory 提供创建对象的接口. ConcreteFactory 提供真正创建对象的实现类,用于组合并创建不同的对象, ...

  10. Headfirst设计模式的C++实现——抽象工厂(Abstract Factory)

    Dough.h #ifndef _DOUGH_H #define _DOUGH_H class Dough { }; #endif ThinCrustDough.h #ifndef _THIN_CRU ...

随机推荐

  1. 洛谷P1216数字三角形题解

    题目 这道题是一个典型的DP,可以用倒推,顺推的方法,来解这道题.当然用不同的方法他的循环次序是不一样的,所以我们一定要深刻地理解题目的大意,再采用状态转移方程与边界每次求出最优解,并记录循环一遍后就 ...

  2. Django+Xadmin打造在线教育系统(七)

    全局导航&个人中心&全局搜索 配置全局导航 让index页面也继承base页面,注意首页有个单独的__index.js__ base页面的导航栏也进行配置 <nav> &l ...

  3. Iroha and a Grid AtCoder - 1974(思维水题)

    就是一个组合数水题 偷个图 去掉阴影部分  把整个图看成上下两个矩形 对于上面的矩形求出起点到每个绿点的方案 对于下面的矩形 求出每个绿点到终点的方案 上下两个绿点的方案相乘后相加 就是了 想想为什么 ...

  4. Linux block(1k) block(4k) 换算 gb

    输入 df  显示1k blocks  大小   再输入  df -h  显示 gb换算大小  结论 block(1k) 计算公式为:  block(1k)   /1024/1000  = xx gb ...

  5. THUSC2017 Day1题解

    THUSC2017 Day1题解 巧克力 题目描述 "人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道." 明明收到了一大块巧克力,里面有若干小块,排成n行m列.每一小块都有 ...

  6. HNOI2017 抛硬币 (FakeBeng)

    除了队长快跑外最难的题吧. 除了需要写\(exLucas\)之外,还教会了我大量的卡常技巧. 首先\(70\)分就是个直接按题意模拟,易得\(ans=\sum_{j=0}^{b} C_{b}^{j}\ ...

  7. 用c#查询各快递物流信息

    前面介绍过<用快递100接口查询各快递物流信息>,里面用的是API接口,但有些快递不支持这种方式,本文介绍的HtmlAPI支持所有快递公司. 支持包括EMS.邮政.顺丰和申通在内的所有公司 ...

  8. 如何在代码中减少if else语句的使用

    前言 代码中嵌套的if/else结构往往导致代码不美观,也不易于理解.面向过程的开发中代码有大量的if else,在java中可以用一些设计模式替换掉这些逻辑,那么在js中是否也有类似的方法用来尽可能 ...

  9. squid详解(正向代理、透明代理、反向代理)

    squid http://www.squid-cache.org/ --官方网址 squid软件主要有两大应用:1,代理上网(正向代理,透明代理) 2,网站静态页面缓存加速(反向代理) 三种代理类型: ...

  10. hdu2586How far away ?(LCA LCATarjan离线)

    题目链接:acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:有n个点,同n-1条带有权值的双向边相连,有m个询问,每个询问包含两个数x,y,求x与y的最短距离. ...