设计模式-抽象工厂模式(Abstract Factory Pattern)结构|原理|优缺点|场景|示例

目录

        设计模式(分类)        设计模式(六大原则)   

    创建型

        工厂方法         抽象工厂模式        

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式的核心目的是将一组相关产品的创建过程封装起来,使得客户端可以使用一个统一的接口来创建这些产品家族中的任何产品,而无需关心具体的实现细节。抽象工厂模式特别适用于处理具有产品族的产品结构,其中产品族是指位于不同等级结构中的一组产品,它们之间可能存在一定的依赖或约束关系。

模式结构

抽象工厂模式通常包含以下角色:

  1. 抽象工厂(Abstract Factory):定义了一个创建产品族的接口,声明了一系列创建不同产品的方法。这些方法返回的是相应产品接口的引用。

  2. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责生成一个或多个具体产品族中的产品对象。

  3. 抽象产品(Abstract Product):定义了产品族中每种产品的公共接口,它是所有具体产品类的基类或接口。

  4. 具体产品(Concrete Product):实现了抽象产品接口,是产品族中每种产品的具体实现。

工作原理

  • 客户端:通过调用具体工厂的接口来创建所需的产品对象,无需直接实例化具体产品类。
  • 具体工厂:实现了抽象工厂接口中定义的创建产品的方法,根据工厂的类型返回相应具体产品族中的产品对象。
  • 抽象产品:为产品对象定义了通用的接口,使得客户端可以使用抽象产品类型的引用来处理各种具体产品对象,无需关心具体产品类型。
  • 具体产品:实现了抽象产品的接口,提供了具体产品的功能实现。

优缺点

优点
  • 封装性:将一组相关产品的创建过程封装在一起,客户端无需了解具体产品的创建细节。
  • 一致性:提供一个统一的接口来创建相关或依赖的对象,保持产品族内部的一致性。
  • 灵活性与扩展性:当需要增加新的产品族时,只需增加一个新的具体工厂和相关产品类即可,不影响已有代码,符合“开闭原则”。
  • 隔离变化:通过抽象工厂隔离了高层模块与具体产品的依赖关系,使得高层模块无需关心产品族内部的变化。
缺点
  • 增加复杂性:对于简单系统,引入抽象工厂可能会增加不必要的复杂性。
  • 产品族扩展困难:如果产品族中添加新产品,不仅需要修改抽象工厂和具体工厂,还可能影响到使用抽象工厂的客户端代码。
  • 类的层级结构复杂:随着产品种类的增加,可能会导致类的层级结构变得复杂。

适用场景

  • 产品族内有多组相关产品:当一个系统需要创建一系列相关或依赖的产品对象时,且这些产品之间存在一定的约束或兼容性要求,抽象工厂模式非常适合。
  • 需要隔离高层模块与具体产品的依赖:如果希望高层模块不直接依赖具体产品的创建过程,可以通过抽象工厂来封装创建细节。
  • 系统需要支持多种产品系列:如果有多种产品系列(如不同操作系统上的图形界面组件),且希望在不修改客户端代码的情况下引入新的产品系列,可以使用抽象工厂模式。

代码示例(以Java为例)

// 抽象产品(操作系统相关的UI组件接口)
interface Button {
    void display();
}

interface TextField {
    void display();
}

// 具体产品(Windows平台的UI组件)
class WindowsButton implements Button {
    @Override
    public void display() {
        System.out.println("Displaying Windows button");
    }
}

class WindowsTextField implements TextField {
    @Override
    public void display() {
        System.out.println("Displaying Windows text field");
    }
}

// 具体产品(MacOS平台的UI组件)
class MacOSButton implements Button {
    @Override
    public void display() {
        System.out.println("Displaying MacOS button");
    }
}

class MacOSTextField implements TextField {
    @Override
    public void display() {
        System.out.println("Displaying MacOS text field");
    }
}

// 抽象工厂
interface UIFactory {
    Button createButton();
    TextField createTextField();
}

// 具体工厂(Windows平台UI工厂)
class WindowsUIFactory implements UIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextField createTextField() {
        return new WindowsTextField();
    }
}

// 具体工厂(MacOS平台UI工厂)
class MacOSUIFactory implements UIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }

    @Override
    public TextField createTextField() {
        return new MacOSTextField();
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        UIFactory windowsFactory = new WindowsUIFactory();
        UIFactory macosFactory = new MacOSUIFactory();

        Button windowsButton = windowsFactory.createButton();
        TextField windowsTextField = windowsFactory.createTextField();
        windowsButton.display();
        windowsTextField.display();

        Button macosButton = macosFactory.createButton();
        TextField macosTextField = macosFactory.createTextField();
        macosButton.display();
        macosTextField.display();
    }
}

 在这个Java示例中:

  • ButtonTextField接口作为抽象产品,定义了UI组件的基本行为。
  • WindowsButtonWindowsTextFieldMacOSButtonMacOSTextField类是具体产品,它们分别实现了对应平台的UI组件功能。
  • UIFactory接口作为抽象工厂,定义了创建按钮和文本字段的方法。
  • WindowsUIFactoryMacOSUIFactory类是具体工厂,它们实现了UIFactory接口,分别创建对应平台的UI组件。
  • Main类的main方法中,客户端代码通过创建不同平台的工厂对象,然后调用工厂方法来创建所需UI组件,无需关心组件的具体实现细节。通过切换不同的工厂对象,可以轻松地在不同平台的UI风格之间切换。

这个Java示例展示了抽象工厂模式的应用,通过抽象工厂创建相关产品族中的对象,使得客户端代码与具体产品的实现细节解耦,增强了系统的灵活性和可扩展性。当需要支持新的操作系统平台时,只需添加新的具体工厂和UI组件类即可,无需修改已有的客户端代码。

代码示例(以Python为例)

# 抽象产品(操作系统相关的UI组件)
class Button:
    def display(self):
        raise NotImplementedError("Subclasses must implement this abstract method")

class TextField:
    def display(self):
        raise NotImplementedError("Subclasses must implement this abstract method")

# 具体产品(Windows平台的UI组件)
class WindowsButton(Button):
    def display(self):
        return "Displaying Windows button"

class WindowsTextField(TextField):
    def display(self):
        return "Displaying Windows text field"

# 具体产品(MacOS平台的UI组件)
class MacOSButton(Button):
    def display(self):
        return "Displaying MacOS button"

class MacOSTextField(TextField):
    def display(self):
        return "Displaying MacOS text field"

# 抽象工厂
class UIFactory:
    def create_button(self):
        raise NotImplementedError("Subclasses must implement this abstract method")

    def create_text_field(self):
        raise NotImplementedError("Subclasses must implement this abstract method")

# 具体工厂(Windows平台UI工厂)
class WindowsUIFactory(UIFactory):
    def create_button(self):
        return WindowsButton()

    def create_text_field(self):
        return WindowsTextField()

# 具体工厂(MacOS平台UI工厂)
class MacOSUIFactory(UIFactory):
    def create_button(self):
        return MacOSButton()

    def create_text_field(self):
        return MacOSTextField()

# 客户端代码
def main():
    windows_factory = WindowsUIFactory()
    macos_factory = MacOSUIFactory()

    button = windows_factory.create_button()
    text_field = windows_factory.create_text_field()
    print(button.display())
    print(text_field.display())

    button = macos_factory.create_button()
    text_field = macos_factory.create_text_field()
    print(button.display())
    print(text_field.display())

if __name__ == "__main__":
    main()

在这个Python示例中:

  • ButtonTextField类作为抽象产品,定义了UI组件的基本接口。
  • WindowsButtonWindowsTextFieldMacOSButtonMacOSTextField类是具体产品,它们分别实现了对应平台的UI组件功能。
  • UIFactory类作为抽象工厂,定义了创建按钮和文本字段的方法。
  • WindowsUIFactoryMacOSUIFactory类是具体工厂,它们实现了UIFactory接口,分别创建对应平台的UI组件。
  • 客户端代码中,通过创建不同平台的工厂对象,然后调用工厂方法来创建所需UI组件,无需关心组件的具体实现细节。通过切换不同的工厂对象,可以轻松地在不同平台的UI风格之间切换。

这个例子展示了抽象工厂模式在Python中的应用,通过抽象工厂创建相关产品族中的对象,使得客户端代码与具体产品的实现细节解耦,增强了系统的灵活性和可扩展性。当需要支持新的操作系统平台时,只需添加新的具体工厂和UI组件类即可,无需修改已有的客户端代码。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/556058.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 字符串 Base64

因消息传输的需要,我们需要对大量文本的字符串进行一下 Base64 转换。 这样的好处是因为在传输的字符串中可能有存在一些特殊字符,这些特殊在经过网络传输的时候会出现编码的问题,并且会影响传输稳定性。 使用 Base64 可以避免这个问题。 方…

数据库--Sqlite3

1、思维导图 2sqlite3在linux中是实现数据的增删&#xff0c;改 #include<myhead.h> int main(int argc, const char *argv[]) { //1、定义一个数据库句柄指针 sqlite3* ppDb NULL; //2、创建或打开数据库 if(sqlite3_open("./mydb…

深入解析Apache Hadoop YARN:工作原理与核心组件

什么是YARN&#xff1f; YARN&#xff08;Yet Another Resource Negotiator&#xff09;是Apache Hadoop生态系统中的一个重要组件&#xff0c;用于资源管理和作业调度。它是Hadoop 2.x版本中的一个关键特性&#xff0c;取代了旧版本中的JobTracker和TaskTracker。YARN的设计目…

ElasticSearch实战之项目搜索高亮

文章目录 1. 前情配置2、数据操作2.1 操作API2.2 数据入库 3. 高亮搜索3.1 方法封装3.2 高亮搜索 1. 前情配置 为满足ElasticSearch可在项目中实现搜索高亮&#xff0c;我们需要先做一些前情配置 导入ElasticSearch依赖 <dependency><groupId>org.springframewor…

【Flutter】多语言方案一:flutter_localizations 与 GetX 配合版

系列文章目录 多语言方案&#xff1a;flutter_localizations 与 GetX 配合版&#xff0c;好处&#xff1a;命令行生成多语言字符串的引用常量类&#xff0c;缺点&#xff1a;切换语言以后&#xff0c;主界面需要手动触发setState&#xff0c;重绘将最新的Locale数据设置给GetM…

【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析 题目链接&#xff1a;912. 排序数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路&#xff1a; 快速排序作为一种经典的排序算法&#xff0c;其核心思想在于通过“分而治之”的策略&#xff…

Idea修改【Help->Edit Custom VM Options...】后,导致idea无法正常启动的解决方法

一、错误场景: 二、解决方法&#xff1a; 修改文件路径&#xff1a;C:\Users\tianjm&#xff08;写自己的用户名&#xff09;\AppData\Roaming\JetBrains\IdeaIC2024.1&#xff08;选自己安装的版本&#xff09;

Linux 网络编程项目--简易ftp

主要代码 config.h #define LS 0 #define GET 1 #define PWD 2#define IFGO 3#define LCD 4 #define LLS 5 #define CD 6 #define PUT 7#define QUIT 8 #define DOFILE 9struct Msg {int type;char data[1024];char secondBuf[128]; }; 服务器: #i…

传统零售行业如何做数字化转型?

传统零售行业的数字化转型是一个系统性的过程&#xff0c;涉及到企业的多个方面。以下是一些关键步骤和策略&#xff0c;帮助传统零售企业实现数字化转型&#xff1a; 1、明确转型目标和战略 首先&#xff0c;企业需要明确数字化转型的目标和战略。包括确定企业的核心竞争力、…

Java内存模型和 JVM 内存运行时

文章目录 前言一、什么是Java 的内存模型&#xff1f;二、什么是 JVM 的运行时数据区Java8 之前和之后的区别JVM 内存模型JVM 内存区域JVM 内存垃圾回收JVM如何判断哪些对象不在存活&#xff1f;JVM运行过程中如何判断哪些对象是垃圾&#xff1f; JVM 垃圾回收Java8 中的 jvm如…

.rmallox勒索病毒来袭:如何守护您的数据安全?

引言&#xff1a; 随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;其中勒索病毒更是成为了网络安全领域的一大难题。.rmallox勒索病毒作为一种典型的恶意软件&#xff0c;通过加密受害者文件并勒索赎金的方式&#xff0c;给企业和个人带来了巨大的经济损…

指纹浏览器如何高效帮助TikTok账号矩阵搭建?

TikTok的账号矩阵&#xff0c;可能听起来还比较陌生&#xff0c;但随着TikTok业务已经成为吃手可热的跨境业务&#xff0c;TikTok多账号矩阵已成为流行策略。但它有什么优点呢&#xff1f;操作多个帐户会导致被禁止吗&#xff1f;如何有效地建立账户矩阵开展业务&#xff1f;这…

爬虫 | 基于 requests 实现加密 POST 请求发送与身份验证

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目旨在实现一个简单的 Python 脚本&#xff0c;用于向指定的 URL 发送 POST 请求&#xff0c;并通过特定的加密算法生成请求头中的签名信息。这个脚本的背后是与某个特定的网络服务交互&#xff0c;发送特定格式的 JSON 数据…

深入理解MySQL中的UPDATE JOIN语句

在MySQL数据库中&#xff0c;UPDATE语句用于修改表中现有的记录。有时&#xff0c;我们需要根据另一个相关联表中的条件来更新表中的数据。这时就需要使用UPDATE JOIN语句。最近我们遇到了这样的需求&#xff1a;我们有一张历史记录表&#xff0c;其中一个字段记录了用,连接的多…

网络爬虫软件学习

1 什么是爬虫软件 爬虫软件&#xff0c;也称为网络爬虫或网络蜘蛛&#xff0c;是一种自动抓取万维网信息的程序或脚本。它基于一定的规则&#xff0c;自动地访问网页并抓取需要的信息。爬虫软件可以应用于大规模数据采集和分析&#xff0c;广泛应用于舆情监测、品牌竞争分析、…

在 Linux 终端中创建目录

目录 ⛳️推荐 前言 在 Linux 中创建一个新目录 创建多个新目录 创建多个嵌套的子目录 测试你的知识 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 前言 在本系列的这一部…

Day09 React———— 第九天

ReactRoter 一个路径 path 对应一个组件 component 当我们在浏览器中访问一个 path 的时候&#xff0c;path 对应的组件会在页面中进行渲染 基础用法 import { createBrowserRouter, RouterProvider } from "react-router-dom"; const router createBrowserRoute…

解决Mac使用Vscode无法调用外部终端

前言 今天遇到一个很奇怪的问题&#xff0c;之前好好的用Vscode还能调用外部终端&#xff0c;怎么今天不行了&#xff1f;问题出在哪里呢&#xff1f;请听我娓娓道来。 检查配置文件 我查看了一下配置文件&#xff0c;发现配置文件都是调用外部控制台&#xff0c;没毛病啊。 …

linux启动minicom、u-boot的常用命令、网络命令tftp、nfs/根文件系统、u-boot的bootargs环境变量

linux启动minicom sudo minicom -con进入minicom界面&#xff1a; 打开单片机 在打开之后&#xff0c;我们通过 printenv查看环境配置 在修改配置之前&#xff0c;我们最好先将环境初始化一下&#xff0c;初始化代码为 nand erase.chipu-boot的常用命令 尽管u-boot是一个…

Torch 模型 感受野可视化

前言&#xff1a;感受野是卷积神经网络 (CNN) 中一个重要的概念&#xff0c;它表示 CNN 每一层输出的特征图上的像素点在输入图像上映射的区域。感受野的大小和形状直接影响到网络对输入图像的感知范围和精度&#xff0c;进而调整网络结构、卷积核大小和步长等参数&#xff0c;…