什么是抽象工厂模式?
的有关信息介绍如下:
上一篇我们介绍了工厂方法模式,本文,我们继续介绍它的兄弟,抽象工厂模式(Abstract Factory Pattern)。
在工厂方法模式中,我们通过一个工厂方法接口来创建产品,而创建哪类产品,由具体的工厂对象来决定。抽象工厂模式和工厂方法模式的功能很类似,只是把“产品”,变成了“产品族”。产品族就意味着这是一系列有关联的、一起使用的对象。我们当然也可以为产品族中的每个产品定义一个工厂方法接口,但这显得有些冗余,因为一起使用通常也意味着同时创建,所以把它们放到同一个抽象工厂来创建会更合适。
在简单的分布式应用系统(示例代码工程)中,我们有一个 Monitor 监控系统模块,该模块可以看成是一个简单的 ETL 系统,负责对监控数据的采集、处理、输出。整个模块被设计为插件化风格的架构,Pipeline是数据处理的流水线,其中包含了 Input、Filter 和 Output 三类插件,Input 负责从各类数据源中获取监控数据,Filter 负责数据处理,Output 负责将处理后的数据输出。更详细的设计思想我们在桥接模式一篇再做介绍,本文主要聚焦如何使用抽象工厂模式来解决各类插件的配置加载问题。
作为 ETL 系统,Monitor 模块应该具备灵活的扩展能力来应对不同的监控数据类型,因此,我们希望能够通过配置文件来定义 Pipeline 的行为。比如,下面就是一个 yaml 格式的配置内容:
另外,我们也希望 Monitor 模块支持多种类型的配置文件格式,比如,json 配置内容应该也支持:
所以,整体的效果是这样的:
可以看出,配置管理子模块中对象之间的关系,很符合抽象工厂模式的 UML 的结构,其中产品族就是 4 个插件配置对象,conf.Input、conf.Filter、conf.Output、conf.Pipeline,因此,我们下面使用抽象工厂模式来实现该子模块。
首先,我们先把各个配置对象(产品)定义好:
在 Java/C++ 等面向对象的编程语言中,我们定义一个产品的不同实现的时,通常采用继承的方式,也即先定义一个基类封装好公共逻辑,再定义不同的继承自该基类的不同子类来实现具体的逻辑。比如,对于 Input 配置对象,在 Java 中可能是这样定义的:
但是在 Go 语言中并没有继承的概念,也无法定义抽象基类,因此,我们通过定义一个函数对象 loadConf 来实现多态,它的类型是 func(conf string, item interface{}) error,具体做的事情就是解析 conf 字符串(配置文件内容),然后完成 item 的赋值。
接下来,我们定义抽象工厂接口:
然后是不同的实现:
使用方法如下;
总结实现抽象工厂模式的几个关键点:
很多同学容易将工厂方法模式和抽象工厂模式混淆,工厂方法模式主要应用在单个产品的实例化场景;抽象工厂模式则应用在“产品族”的实例化场景,可以看成是工厂方法模式的一种演进。
另外,抽象工厂接口的实现类,有时也会通过单例模式来实现。



