当前位置: 首页 > news >正文

抽象工厂设计模式 Abstract Factory

抽象工厂

抽象工厂设计模式是一种创建模式,它提供了一个用于创建相关或从属对象族的接口,而无需指定其具体类。
它在以下情况下特别有用:
您需要创建必须一起使用并且是一致系列的一部分的对象(例如,按钮、复选框和菜单等 GUI 元素)。
您的系统必须支持多种配置、环境或产品变体(例如,浅色与深色主题、Windows 与 macOS 外观)。

您希望在相关对象之间强制保持一致性,确保它们都是从同一个工厂创建的。
抽象工厂模式将 对象创建封装到工厂接口中。

每个具体工厂实现接口并生成一组完整的相关对象。这可确保您的代码保持可扩展、一致并与特定产品实现松散耦合。
让我们通过一个真实世界的示例,看看如何应用抽象工厂模式来构建一个灵活、可维护的系统,并且能够在没有条件逻辑的情况下支持多个可互换的产品系列。

问题:特定于平台的 UI
假设你正在构建一个必须同时支持 Windows 和 macOS 的跨平台桌面应用程序。

为了提供良好的用户体验,您的应用程序应 为每个作系统呈现具有本机外观的 UI 组件,例如:

按钮
复选框
文本字段
菜单
朴素实现:条件 UI 组件实例化
在第一次尝试中,您可以实现特定于平台的 UI 组件,如下所示:
Windows UI 元素

  public class WindowsButton implements Button {@Overridepublic void paint() {System.out.println("Painting a Windows-style button.");}@Overridepublic void onClick() {System.out.println("Windows button clicked.");}
}public class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("Painting a Windows-style checkbox.");}@Overridepublic void onSelect() {System.out.println("Windows checkbox selected.");}
}

MacOS UI元素

public class MacOSButton implements Button {@Overridepublic void paint() {System.out.println("Painting a macOS-style button.");}@Overridepublic void onClick() {System.out.println("MacOS button clicked.");}
}public class MacOSCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("Painting a macOS-style checkbox.");}@Overridepublic void onSelect() {System.out.println("MacOS checkbox selected.");}
}

然后,在应用程序逻辑中,您最终会执行以下作:

public class App {public static void main(String[] args) {String os = System.getProperty("os.name");if (os.contains("Windows")) {WindowsButton button = new WindowsButton();WindowsCheckbox checkbox = new WindowsCheckbox();button.paint();checkbox.paint();} else if (os.contains("Mac")) {MacOSButton button = new MacOSButton();MacOSCheckbox checkbox = new MacOSCheckbox();button.paint();checkbox.paint();}}
}

为什么这种方法会失败
虽然此设置适用于两个平台上的两个 UI 组件,但随着应用的增长,它很快就会成为一场噩梦。

  1. 1. 与混凝土类紧密耦合
    您的主应用程序逻辑与特定于平台的类 (, , 等) 紧密绑定。这意味着无论在何处创建 UI 组件,都必须手动检查作系统。WindowsButtonMacOSCheckbox
  2. 2. 无抽象或多态性
    不能笼统地处理按钮或复选框。没有像或可以使用的通用界面 。ButtonCheckbox
  3. 3. 代码重复和重复
    每个特定于平台的块都复制了类似的逻辑——实例化按钮、复选框、菜单等。你将在整个代码库中重复此条件分支。
  4. 4. 可扩展性问题
    当您:

添加新平台(例如 Linux)?

添加新组件(例如,、、)?TextFieldSliderMenuBar

您必须:

为每个平台添加新的具体类

修改代码中出现特定于平台的逻辑的每个位置

破坏现有行为的风险

  1. 5. 违反开放/关闭原则
    任何新的变体都需要修改现有代码。您的 UI 创建逻辑不开放扩展,但对重大更改非常开放。

我们真正需要什么
我们需要一种方法来:

按平台对相关组件(按钮、复选框等)进行分组

将特定于平台的创建逻辑封装到工厂中

以多态方式处理 UI 组件,无论平台如何

轻松添加新的 UI 元素系列,而无需修改应用程序的核心逻辑

这就是抽象工厂模式的用武之地。

抽象工厂模式
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的族,而无需指定其具体类。

在我们的例子中,我们想要创建一个 UI 组件系列(如 、 、 等),这些组件在不同平台(例如 Windows 或 macOS)上的外观和行为不同,但向应用程序公开相同的界面。ButtonCheckboxTextField

抽象工厂模式通过以下方式帮助我们实现这一目标:

定义抽象 UI 工厂接口(例如 GUIFactory)

为每个平台实施一个具体工厂(例如, WindowsFactoryMacOSFactory)

为每种类型的组件公开一组一致的接口(例如,, ButtonCheckbox)

让客户端使用这些接口,而无需担心特定于平台的实现

类图

 

  1. 1. 抽象工厂 (GUIFactory)
    定义用于 创建相关产品系列的通用接口。

通常包括工厂方法,如 、 、 等。createButton()createCheckbox()createTextField()

客户端依靠此接口创建对象,而无需知道其具体类型。

  1. 2. 混凝土厂 (, WindowsFactoryMacOSFactory)
    实现抽象工厂接口。

创建 属于特定系列或平台的具体产品变型。

每个工厂都确保其生产的所有组件都是兼容的(即属于同一平台/主题)。

  1. 3. 抽象产品 (, ButtonCheckbox)
    为 一组相关组件定义接口或抽象类。

给定类型(例如,,)的所有产品变体都 将实现这些接口。WindowsButtonMacOSButton

  1. 4. 混凝土产品 (, WindowsButtonMacOSCheckbox)
    实现抽象产品接口。

包含 组件的特定于平台的逻辑和外观。

  1. 5. 客户 (Application)
    使用抽象工厂和抽象产品接口。

完全不知道它正在使用的具体类——它只与工厂和产品接互。

可以通过更改出厂方式切换整个产品系列(例如,从 Windows 切换到 macOS),而无需接触 UI 逻辑。

实现抽象工厂
让我们实现一个系统,让我们的应用程序可以为 Windows 和 macOS 生成具有本机外观的 UI 组件(按钮、复选框), 而无需硬编码平台检查或复制逻辑。

  1. 1. 定义抽象产品接口
    我们首先定义客户端使用的产品接口。

Button

public interface Button {void paint();void onClick();
}

Checkbox

public interface Checkbox {void paint();void onSelect();
}
  1. 2. 创建具体产品类
    这些实现特定于平台的逻辑。

Windows 组件

public class WindowsButton implements Button {@Overridepublic void paint() {System.out.println("Painting a Windows-style button.");}@Overridepublic void onClick() {System.out.println("Windows button clicked.");}
}public class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("Painting a Windows-style checkbox.");}@Overridepublic void onSelect() {System.out.println("Windows checkbox selected.");}
}

macOS 组件

public class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("Painting a Windows-style checkbox.");}@Overridepublic void onSelect() {System.out.println("Windows checkbox selected.");}
}public class MacOSCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("Painting a macOS-style checkbox.");}@Overridepublic void onSelect() {System.out.println("MacOS checkbox selected.");}
}
  1. 3. 定义抽象工厂
    这是用于创建相关产品系列的界面。
public interface GUIFactory {Button createButton();Checkbox createCheckbox();
}
  1. 4. 实施混凝土工厂
    每个工厂都会创建特定于平台的组件变体。

WindowsFactory

public class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}

MacOSFactory

public class MacOSFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacOSButton();}@Overridepublic Checkbox createCheckbox() {return new MacOSCheckbox();}
}
  1. 5. 客户端代码 – 仅使用抽象接口
    客户端代码根据作系统选择工厂,并使用它来创建 UI 组件。
public class Application {private final Button button;private final Checkbox checkbox;public Application(GUIFactory factory) {this.button = factory.createButton();this.checkbox = factory.createCheckbox();}public void renderUI() {button.paint();checkbox.paint();}
}
  1. 6. 申请切入点

输出(在 macOS 上)

Painting a macOS-style button.
Painting a macOS-style checkbox.

输出(在 Windows 上)

Painting a Windows-style button.
Painting a Windows-style checkbox.

我们取得了什么成就
平台独立性:应用程序代码从不引用特定于平台的类
一致性:按钮和复选框始终与所选作系统样式匹配
开放/封闭原则:在不修改现有工厂或组件的情况下添加对 Linux 或 Android 的支持
可测试性和灵活性:工厂可以轻松更换以进行测试或主题
其他资料:

https://pan.baidu.com/s/1c1oQItiA7nZxz8Rnl3STpw?pwd=yftc
https://pan.quark.cn/s/dec9e4868381

http://www.lryc.cn/news/625190.html

相关文章:

  • yum安装搭建lamp架构部署WordPress个人论坛
  • 美图披露半年报:AI应用取得突破,净利润同比大增71.3%
  • 上周60+TRO案件,波比的游戏时间/丹迪世界/飞盘/迪奥/多轮维权,手表/汽车品牌持续发力,垃圾桶专利等新增侵权风险!
  • 【MongoDB】多种聚合操作详解,案例分析
  • 启发式合并
  • powershell中的cmdlet
  • 【每日一题】Day 7
  • MySQL架构和储存引擎
  • Web安全 - 构建安全可靠的API:基于国密SM2/SM3的文件上传方案深度解析
  • 多智能体架构设计:从单Agent到复杂系统的演进逻辑
  • 人工智能 | 基于大数据的皮肤病症状数据可视化分析系统(matlab源码)
  • 发布npmjs组件库
  • AopAutoConfiguration源码阅读
  • 鼠标右键没有“通过VSCode打开文件夹”
  • JVM学习笔记-----类加载
  • FPGA-Vivado2017.4-建立AXI4用于单片机与FPGA之间数据互通
  • Google 的 Opal:重新定义自动化的 AI 平台
  • WPF 打印报告图片大小的自适应(含完整示例与详解)
  • Rust 入门 生命周期-next2 (十九)
  • 牛津大学xDeepMind 自然语言处理(1)
  • Centos7 使用lamp架构部署wordpress
  • 接口和抽象类的区别(面试回答)
  • 【深度长文】Anthropic发布Prompt Engineering全新指南
  • Java面向对象三大特性:封装、继承、多态深度解析与实践应用
  • ⭐CVPR2025 RigGS:从 2D 视频到可编辑 3D 关节物体的建模新范式
  • 音频分类模型笔记
  • OOP三大特性
  • 【计算机视觉与深度学习实战】05计算机视觉与深度学习在蚊子检测中的应用综述与假设
  • 网络基础——协议认识
  • Pytest项目_day18(读取ini文件)