设计模式(3)抽象工厂模式(Abstract Factory)
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)的更多相关文章
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...
- 【设计模式】抽象工厂模式 Abstract Factory Pattern
简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...
- 二十四种设计模式:抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式(Abstract Factory Pattern) 介绍提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例有Message和MessageModel,Messag ...
- 【UE4 设计模式】抽象工厂模式 Abstract Factory Pattern
概述 描述 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类:具体的工厂负责实现具体的产品实例 抽象工厂中每个工厂可以创建多种产品(如苹果公司生产iPhone.iPad): 工厂方法 ...
- 设计模式之抽象工厂模式(Abstract Factory Pattern)
一.抽象工厂模式的由来 抽象工厂模式,最开始是为了解决操作系统按钮和窗体风格,而产生的一种设计模式.例如:在windows系统中,我们要用windows设定的按钮和窗体,当我们切换Linux系统时,要 ...
- 设计模式 笔记 抽象工厂模式 Abstract Factory
//---------------------------15/04/09---------------------------- //Abstract Factory 抽象工厂----对象创建型模式 ...
- .NET设计模式(2):1.2 抽象工厂模式(Abstract Factory)
概述 抽象工厂模式(Abstract Factory)是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口 ...
- 设计模式 - 抽象工厂模式(abstract factory pattern) 具体解释
抽象工厂模式(abstract factory pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/2709 ...
- 抽象工厂模式(Abstract Factory)C#实例
抽象工厂模式(Abstract Factory)C#实例 本文出处http://www.dofactory.com/net/abstract-factory-design-pattern 一.场景描述 ...
- 浅谈C++设计模式之抽象工厂(Abstract Factory)
抽象工厂(Abstract Factory)模式是为了提供一系列相关或相互依赖对象的接口.对象创建型模式的一种. 客户Client 抽象工厂接口AbstractFactory 抽象工厂的实现类Conc ...
随机推荐
- 【锋利的jQuery】中全局事件ajaxStart、ajaxStop不执行
最近一直都在研究[锋利的jQuery],确实是一本好书,受益匪浅.但由于技术发展及版本更新等原因,里面还是有些坑需要踩的. 比如:第六章七节中提到的全局事件ajaxStart.ajaxStop照着案例 ...
- JS事件及其兼容用法
JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间. 1.事件流:描述的是从页面中接收事件的顺序. IE提出的事件冒泡流:事件开始由最具体的 ...
- 有关苹果无法导出p12证书的问题解决办法。
原因一 所选类型选择错误.解决办法:左侧有两个分类,一个是钥匙串,一个是种类,要选择种类中的我的证书或者证书.然后在右侧证书列表中,右键导出即可. 原因二 使用钥匙串生成的证书有问题,格式为(cert ...
- git视频教程
git 精简版视频教程-2小时快速入门精华版,小教程很快就可以看完. 旺旺 QQ:Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有非常高的逼格,简单来说就是:高端大气上档次. 这么 ...
- 验证表格多行某一input是否为空
function checkTableKeyWordVal(tableId){ var result = true; $("#"+tableId+" tbody tr&q ...
- HTML行内元素、块状元素、行内块状元素的区别
HTML可以将元素分类方式分为行内元素.块状元素和行内块状元素三种.首先需要说明的是,这三者是可以互相转换的,使用display属性能够将三者任意转换: (1)display:inline;转换为行内 ...
- 【Android Developers Training】 11. 支持不同语言
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- python3中socket套接字的编码问题解决
一.TCP 1.tcp服务器创建 #创建服务器 from socket import * from time import ctime #导入ctime HOST = '' #任意主机 PORT = ...
- 1.如何安装maven
[确认]在CMD命令行中输入echo %JAVA_HOME%,查看JAVA_HOME是否配置.在CMD命令行中输入java -v,查看jdk是否正确安装. [下载]从http://maven.ap ...
- iOS 本地视频和网络视频流播放
需求:最近公司需要做一个楼宇对讲的功能:门口机(连接WIFI)拨号对室内机(对应的WIFI)的设备进行呼叫,室内机收到呼叫之后将对收到的数据进行UDP广播的转发,手机(连接对应的WIFI)收到视频流之 ...