设计模式学习之抽象工厂模式

本文介绍了设计模式中的工厂方法模式和抽象工厂模式,通过GUI组件创建的例子阐述了两种模式的区别和应用场景。在工厂方法模式中,每个工厂生产一类产品,而在抽象工厂模式中,工厂能生产一系列相关产品,确保同一风格或变体的产品可以搭配使用。文章通过代码示例展示了如何在不同操作系统环境下使用不同的GUI组件工厂。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
设计模式系列往期文章

  1. 设计模式学习之策略模式
  2. 设计模式学习之策略模式在前端的应用
  3. 设计模式学习之简单工厂模式
  4. 设计模式学习之工厂方法模式

如果你已经理解了工厂方法模式,那你能够很快的明白抽象工厂模式。

温习:什么是工厂方法模式

我们先温习一下什么是工厂方法模式——工厂方法模式定义了一个工厂类接口,基于这个接口实现多个具体的工厂类,每个工厂类负责生产一种产品,类图如下图所示:
在这里插入图片描述

问题引入:什么是抽象工厂模式

那么,什么是抽象工厂模式呢,我们可以把工厂方法模式看做是极端情况下的抽象工厂模式——即工厂类只生产一类产品,如果每个工厂类能够生产多类产品,这样的工厂模式就是抽象工厂模式。举个栗子,假设某个家具工厂能够生产椅子、沙发、咖啡桌等一系列家具,每种家具有有多种风格(如装饰风、维多利亚风、现代风格等),用户肯定希望买一套相同风格的家具而不是混搭,因此可以设置多个生产线,每个生产线只生产一种风格的家具,如下图所示:
在这里插入图片描述
因此家具生产这个工厂类就可能设计成下面的样子,每个工厂能够生产椅子、咖啡桌和沙发:
在这里插入图片描述
在上面这种应用场景中,我们就需要使用抽象工厂模式,其主要特点就是:工厂能够生产多种产品,同一个工厂生产出来的产品应该具有类似的风格/应用场景(正如上面的家具的例子)。类图结构如下图所示:
在这里插入图片描述

代码演示

我们继续扩展设计模式学习之工厂方法模式一文中的例子,由于环境不同,在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 中创建产品的方法变多了。

类图

抽象工厂模式的类图如下图所示:
在这里插入图片描述
对应的plantUML绘图代码为:

@startuml

skinparam linetype ortho

package "Abstract Factory" <<Frame>> {
  interface ProductAIntf {
    + method()
  }

  interface ProductBIntf {
      + method()
    }

  interface FactoryIntf {
    + createProductA()
    + createProductB()
  }

  class ConcreteProductA1 {
    + method()
  }

  class ConcreteProductA2 {
    + method()
  }

  class ConcreteProductB1 {
      + method()
    }

    class ConcreteProductB2 {
      + method()
    }

  class ConcereteFactoryA {
    + createProductA()
    + createProductB()
  }

  class ConcereteFactoryB {
    + createProductA()
    + createProductB()
  }

  ProductAIntf <|.. ConcreteProductA1
  ProductAIntf <|.. ConcreteProductA2

  ProductBIntf <|.. ConcreteProductB1
  ProductBIntf <|.. ConcreteProductB2

  FactoryIntf <|.. ConcereteFactoryA
  FactoryIntf <|.. ConcereteFactoryB

  ConcreteProductA1 <.. ConcereteFactoryA
  ConcreteProductA2 <.. ConcereteFactoryA

  ConcreteProductB1 <.. ConcereteFactoryB
  ConcreteProductB2 <.. ConcereteFactoryB

}
@enduml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值