设计模式(0)简单工厂模式

设计模式(1)单例模式(Singleton)

设计模式(2)工厂方法模式(Factory Method)

源码地址

0 抽象工厂模式简介

0.0 抽象工厂模式定义

抽象工厂模式一般的书面定义为:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类

提供创建接口,无需指定具体实现类,这个原则在简单工厂模式和工厂方法模式篇已经反复讲到了,这是面向接口编程的一个基本准则,很显然,从抽象工厂模式的一般定义中可以看出这也是抽象工厂模式的一个核心,而抽象工厂模式的另一个核心是要解决一系列相关或相依赖对象(产品族)创建的问题。这也是这几种工厂模式的细节区别所在的关键点所在,初学设计模式时往往因为没有认识到这一点区别而对几种工厂模式难以理解

我们可以简单的这么理解,抽象工厂模式不单单要解决对象的创建问题,还要涉及到创建的对象之间的相互依赖或者约束关系。工厂方法模式和简单工厂模式解决了单个产品对象创建的问题,它们只关心单个产品对象的创建,而抽象工厂模式是关注的产品族(多个相互关联对象)的创建,最终创建的产品族形成一个新的产品对象。

抽象工厂模式的结构图如下:

AbstractFactory:抽象工厂类,定义创建某个产品所需相关对象的操作接口

ProductFactory1/ProductFactory2:具体的工厂类,实现抽象工厂定义的方法,负责某个产品所需所有对象创建操作接口的具体实现。

AbstractProductA/AbstractProductB:定义某一类产品对象的接口

ProductA1/ProductA2/ProductB1/ProductB2:具体产品对象的实现

0.1 抽象工厂模式应用场景

如果对上面的文字描述还不能有一个直观的认识,我们仍然从一个简单的应用场景来说明抽象工厂模式的引入时机。

野外商店老板为了更好的服务众英雄,特将店内隐身药水进行了一次升级,分为红瓶装(瓶口直径2cm)、蓝瓶装(瓶口直径5cm)2款,并且2种瓶子分别搭配圆形(2cm)和方形(5cm)两种款式的瓶盖。英雄们来到商店后,只需要将自己的的需要告诉商店老板,老板根据英雄的要求,去取瓶子和盖子进行组装即可。

在应用抽象工厂模式之前,我们很简单的使用简单工厂模式实现这个需求。

定义瓶子接口及实现类

/// <summary>
/// 定义瓶子接口
/// </summary>
public interface IBottle
{
/// <summary>
/// 展示自己的信息
/// </summary>
void ShowInfo();
}
/// <summary>
/// 红色瓶子
/// </summary>
public class RedBottle : IBottle
{
/// <summary>
/// 展示自己的信息
/// </summary>
public void ShowInfo()
{
Console.WriteLine("我是一个热情火辣的红色瓶子,我的瓶口直径是2cm。");
}
}

定义瓶盖接口及实现类

/// <summary>
/// 定义瓶盖接口
/// </summary>
public interface ICap
{
/// <summary>
/// 展示自己的信息
/// </summary>
void ShowInfo();
}
/// <summary>
/// 圆形瓶盖
/// </summary>
public class RoundCap : ICap
{
/// <summary>
/// 展示自己的信息
/// </summary>
public void ShowInfo()
{
Console.WriteLine("我是一个圆形瓶盖,我的直径是2cm。");
}
}
/// <summary>
/// 方形瓶子
/// </summary>
public class SquareCap : ICap
{
/// <summary>
/// 展示自己的信息
/// </summary>
public void ShowInfo()
{
Console.WriteLine("我是一个方形瓶盖,我的直径是5cm。");
}
}

定义创建瓶子和瓶盖的简单工厂

/// <summary>
/// 瓶子创建工厂方法
/// </summary>
public class BottleFactory
{
/// <summary>
/// 创建瓶子对象
/// </summary>
/// <param name="color">瓶子颜色</param>
/// <returns></returns>
public static IBottle CreateBottle(string color)
{
if (color == "red")
return new RedBottle();
if (color == "blue")
return new BlueBottle();
return null;
}
}
/// <summary>
/// 瓶盖创建工厂方法
/// </summary>
public class CapFactory
{
/// <summary>
/// 创建瓶子对象
/// </summary>
/// <param name="shape">瓶盖形状</param>
/// <returns></returns>
public static ICap CreateCap(string shape)
{
if (shape == "round")
return new RoundCap();
if (shape == "square")
return new SquareCap();
return null;
}
}

最终成品组装类定义

/// <summary>
/// 隐形药水组装者
/// </summary>
public class ProductMaker
{
private IBottle _bottle; // 瓶子对象
private ICap _cap; // 瓶盖对象 /// <summary>
/// 创建最终药水对象
/// </summary>
/// <param name="bottleColor"></param>
/// <param name="capShape"></param>
public void MakeProduct(string bottleColor, string capShape)
{
_bottle = BottleFactory.CreateBottle(bottleColor);
_cap = CapFactory.CreateCap(capShape);
Console.WriteLine("准备英雄需要的瓶子和瓶盖。");
_bottle.ShowInfo();
_cap.ShowInfo();
Console.WriteLine("开始往瓶子了灌入隐形药水,然后封上瓶盖。");
}
}

客户端调用

static void Main(string[] args)
{
ProductMaker pm = new ProductMaker();
pm.MakeProduct("red", "round"); // 提供给英雄红瓶子圆盖子的隐形药水
Console.WriteLine();
pm.MakeProduct("blue", "square"); // 提供给英雄蓝瓶子方盖子的隐形药水
Console.ReadLine();
}

这样,我们通过接口进行隔离,解决了不同瓶子,不同盖子创建时,客户端无需关心具体创建过程,只需要告诉工厂需要何种类型的对象即可。但同时会暴露一个很明显的问题就是,我们创建的瓶子和瓶盖2个对象并不是孤立存在的,2个对象之间是有明显的相互关系的,那就是平口尺寸必须和瓶盖尺寸保持一直,否则就会让店老板出现灌装好药水却拧不上盖子的尴尬。此时应该会对上面提到的抽象工厂的定义有进一步的理解,也在这种场景下,是我们必须要引入抽象工厂模式的时候了。

1 抽象工厂模式详解

0、提炼抽象工厂类

根据抽象工厂方法的结构图,我们首先定义个一个抽象工厂类,该抽象工厂定义瓶子和瓶盖2个对象的创建接口。

/// <summary>
/// 抽象工厂类
/// </summary>
public abstract class AbstractFactory
{
/// <summary>
/// 创建瓶子
/// </summary>
/// <returns></returns>
public abstract IBottle CreateBottle(); /// <summary>
/// 创建瓶盖
/// </summary>
/// <returns></returns>
public abstract ICap CreateCap();
}

1、抽象工厂的具体实现

分析产品的组合情况,实际上只存在2种类型的最终产品,红瓶子圆盖子和蓝瓶子方盖子,我们分别定义2个抽象工厂的具体实现类

/// <summary>
/// 红瓶子圆盖子工厂类
/// </summary>
public class RedBottleAndRoundCapFactory : AbstractFactory
{
/// <summary>
/// 创建瓶子
/// </summary>
/// <returns></returns>
public override IBottle CreateBottle()
{
return BottleFactory.CreateBottle("red");
} /// <summary>
/// 创建瓶盖
/// </summary>
/// <returns></returns>
public override ICap CreateCap()
{
return CapFactory.CreateCap("round");
}
}
/// <summary>
/// 蓝瓶子方盖子工厂类
/// </summary>
public class BlueBottleAndSquareCapFactory : AbstractFactory
{
/// <summary>
/// 创建瓶子
/// </summary>
/// <returns></returns>
public override IBottle CreateBottle()
{
return BottleFactory.CreateBottle("blue");
} /// <summary>
/// 创建瓶盖
/// </summary>
/// <returns></returns>
public override ICap CreateCap()
{
return CapFactory.CreateCap("square");
}
}

2、最终产品组装类的修改实现

跟原来的实现相比较,最终产品组装类不在从客户端传入瓶子、瓶盖的参数通过对应的工厂方法创建,而是直接传入已经定义好的瓶子瓶盖组装工厂类对象,能够做到瓶子瓶盖必须配套创建。

/// <summary>
/// 创建最终药水对象
/// </summary>
/// <param name="factory">抽象工厂具体对象</param>
public void MakeProduct(AbstractFactory factory)
{
_bottle = factory.CreateBottle();
_cap = factory.CreateCap();
Console.WriteLine("准备英雄需要的瓶子和瓶盖。");
_bottle.ShowInfo();
_cap.ShowInfo();
Console.WriteLine("开始往瓶子了灌入隐形药水,然后封上瓶盖。");
}

3、客户端调用

ProductMaker pm = new ProductMaker();
AbstractFactory factory = new RedBottleAndRoundCapFactory(); // 提供给英雄红瓶子圆盖子的隐形药水
pm.MakeProduct(factory);
Console.WriteLine();
factory = new BlueBottleAndSquareCapFactory(); // 提供给英雄蓝瓶子方盖子的隐形药水
pm.MakeProduct(factory);
Console.ReadLine();

2 总结

通过创建的多个对象之间的关联关系阐述了抽象工厂模式与其他工厂模式的区别以及使用时机。基于上面的示例,我们可以总结出抽象工厂模式的具有以下优点:

0、分离接口和实现

客户端使用抽象工厂方法来创建需要的对象,只需要传入抽象方法的,无需关注内部具体实现逻辑,实现接口与具体实现的分离解耦。

1、易于产品族切换

一个具体抽象工厂的实现其实就是代表一个产品族,客户端通过参数选用不同的工厂实现,就可以在不同的产品创建中进行切换。

抽象工厂模式的缺点也显而易见,那就是扩展新产品的过程会比较麻烦,比如一个产品族中包含的产品发生了变化,比如增加或减少部件,就需要修改抽象工厂,同时需要修改所有的抽象工厂实现类。

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

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

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

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

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

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

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

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

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

  5. 设计模式之抽象工厂模式(Abstract Factory Pattern)

    一.抽象工厂模式的由来 抽象工厂模式,最开始是为了解决操作系统按钮和窗体风格,而产生的一种设计模式.例如:在windows系统中,我们要用windows设定的按钮和窗体,当我们切换Linux系统时,要 ...

  6. 设计模式 笔记 抽象工厂模式 Abstract Factory

    //---------------------------15/04/09---------------------------- //Abstract Factory 抽象工厂----对象创建型模式 ...

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

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

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

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

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

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

  10. 浅谈C++设计模式之抽象工厂(Abstract Factory)

    抽象工厂(Abstract Factory)模式是为了提供一系列相关或相互依赖对象的接口.对象创建型模式的一种. 客户Client 抽象工厂接口AbstractFactory 抽象工厂的实现类Conc ...

随机推荐

  1. Mavnen的几种依赖关系

    学习mavnen的时候有几种依赖关系 首先,说一下maven的依赖关系用来干什么? 就是用来控制编译.测试.运行三种classpath的关系 1.compile 的范围 当依赖的scope为compi ...

  2. 第一次使用idea从SVN什么checkout项目,一直都是用的eclipse

    IntelliJ IDEA 14 拉取SVN maven 多模块项目 部署tomcat 详细图解!   二话不说 进入主题 我们创建空项目实际上是项目空间 进入主界面 想用svn必须先启用它 选择Su ...

  3. vue 高德地图之玩转周边

    前言:在之前的博客中,有成功引入高德地图,这是以前的地址  vue 调用高德地图. 因为一些需求,需要使用到地图的周边功能. 完整的项目代码请查看  我的github 一 .先看要实现的结果,参考了链 ...

  4. java书系列之——前言

    第1章Java的起源 对于计算机语言的发展史,业界一般认为:B语言导致了C语言的诞生,C语言演变出了C++语言,而C++语言将让位于Java语言.要想更好地了解Java语言,就必须了解它产生的原因.推 ...

  5. JAVA中使用JSONObject对象必备

    JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.本文将快速讲解 JSON 格式,并通过代码示例演示如 ...

  6. AngularJS高级程序设计读书笔记 -- 指令篇 之 自定义指令

    2. 自定义指令(15-17 章) Module.directive(name, factory) 2.1 创建自定义指令的方法 Module.directive(name, factory) 示例 ...

  7. golang 私钥"加密"公钥"解密"

    ---恢复内容开始---   之前工作主要使用C/C++与银行/第三方支付对接,但C/C++无法满足客户"当天给协议明天实盘上载"的开发速度以及现公司一些特殊情况,所以决定用go来 ...

  8. final用法

    1.修饰类 如果一个类被定义为final类型,那么该类无法被其他类继承,该类中的所有方法都是final类型的,字段是否是final类型取决于字段自身的定义. 2.修饰方法 一个方法被定义为final类 ...

  9. linux 升级yum对应的python

    这里记录一下linux 系统升级python对yum带来影响的解决办法 很多人在使用linux系统执行python任务的时候需要升级linux系统自带的python到高级版本.具体如何升级python ...

  10. [leetcode-494-Target Sum]

    You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symb ...