设计模式系列往期文章
- 设计模式学习之策略模式
- 设计模式学习之策略模式在前端的应用
- 设计模式学习之简单工厂模式
- 设计模式学习之工厂方法模式
如果你已经理解了工厂方法模式,那你能够很快的明白抽象工厂模式。
温习:什么是工厂方法模式
我们先温习一下什么是工厂方法模式——工厂方法模式定义了一个工厂类接口,基于这个接口实现多个具体的工厂类,每个工厂类负责生产一种产品,类图如下图所示:
问题引入:什么是抽象工厂模式
那么,什么是抽象工厂模式呢,我们可以把工厂方法模式看做是极端情况下的抽象工厂模式——即工厂类只生产一类产品,如果每个工厂类能够生产多类产品,这样的工厂模式就是抽象工厂模式。举个栗子,假设某个家具工厂能够生产椅子、沙发、咖啡桌等一系列家具,每种家具有有多种风格(如装饰风、维多利亚风、现代风格等),用户肯定希望买一套相同风格的家具而不是混搭,因此可以设置多个生产线,每个生产线只生产一种风格的家具,如下图所示:
因此家具生产这个工厂类就可能设计成下面的样子,每个工厂能够生产椅子、咖啡桌和沙发:
在上面这种应用场景中,我们就需要使用抽象工厂模式,其主要特点就是:工厂能够生产多种产品,同一个工厂生产出来的产品应该具有类似的风格/应用场景(正如上面的家具的例子)。类图结构如下图所示:
代码演示
我们继续扩展设计模式学习之工厂方法模式一文中的例子,由于环境不同,在Windows上和网页端或者MacOS系统中绘制GUI界面的代码实现肯定会有一些差别,而且工厂生产出来的组件肯定不止Button一种类型,在真实的应用场景中还会有输入框、单选框、多选框、下拉框等等组件。这个需求是不是正是抽象工厂模式的应用场景?于是可以设计出如下的类图(其实每个工厂类需要创建的产品不止两个,下图仅是示例):
基于类图给出如下伪代码:
// 抽象工厂接口声明了一组能返回不同抽象产品的方法。这些产品属于同一个系列
// 且在高层主题或概念上具有相关性。同系列的产品通常能相互搭配使用。系列产
// 品可有多个变体,但不同变体的产品不能搭配使用。
interface GUIFactory is
method createButton():Button
method createCheckbox():Checkbox
// 具体工厂可生成属于同一变体的系列产品。工厂会确保其创建的产品能相互搭配
// 使用。具体工厂方法签名会返回一个抽象产品,但在方法内部则会对具体产品进
// 行实例化。
class WinFactory implements GUIFactory is
method createButton():Button is
return new WinButton()
method createCheckbox():Checkbox is
return new WinCheckbox()
// 每个具体工厂中都会包含一个相应的产品变体。
class MacFactory implements GUIFactory is
method createButton():Button is
return new MacButton()
method createCheckbox():Checkbox is
return new MacCheckbox()
// 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
interface Button is
method paint()
// 具体产品由相应的具体工厂创建。
class WinButton implements Button is
method paint() is
// 根据 Windows 样式渲染按钮。
class MacButton implements Button is
method paint() is
// 根据 macOS 样式渲染按钮
// 这是另一个产品的基础接口。所有产品都可以互动,但是只有相同具体变体的产
// 品之间才能够正确地进行交互。
interface Checkbox is
method paint()
class WinCheckbox implements Checkbox is
method paint() is
// 根据 Windows 样式渲染复选框。
class MacCheckbox implements Checkbox is
method paint() is
// 根据 macOS 样式渲染复选框。
// 客户端代码仅通过抽象类型(GUIFactory、Button 和 Checkbox)使用工厂
// 和产品。这让你无需修改任何工厂或产品子类就能将其传递给客户端代码。
class Application is
private field factory: GUIFactory
private field button: Button
constructor Application(factory: GUIFactory) is
this.factory = factory
method createUI() is
this.button = factory.createButton()
method paint() is
button.paint()
// 程序会根据当前配置或环境设定选择工厂类型,并在运行时创建工厂(通常在初
// 始化阶段)。
class ApplicationConfigurator is
method main() is
config = readApplicationConfigFile()
if (config.OS == "Windows") then
factory = new WinFactory()
else if (config.OS == "Mac") then
factory = new MacFactory()
else
throw new Exception("错误!未知的操作系统。")
Application app = new Application(factory)
说明:对比一下工厂方法模式和抽象工厂模式,你会发现代码结构几乎一致,只是GUIFactory
中创建产品的方法变多了。