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

embedded/2024/12/23 3:57:05/

 目录

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

    创建型

        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

     结构型

        适配器模式

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

模式结构

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

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

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

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

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

工作原理

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

优缺点

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

适用场景

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

代码示例(以Java为例)

java">// 抽象产品(操作系统相关的UI组件接口)
interface Button {void display();
}interface TextField {void display();
}// 具体产品(Windows平台的UI组件)
class WindowsButton implements Button {@Overridepublic void display() {System.out.println("Displaying Windows button");}
}class WindowsTextField implements TextField {@Overridepublic void display() {System.out.println("Displaying Windows text field");}
}// 具体产品(MacOS平台的UI组件)
class MacOSButton implements Button {@Overridepublic void display() {System.out.println("Displaying MacOS button");}
}class MacOSTextField implements TextField {@Overridepublic void display() {System.out.println("Displaying MacOS text field");}
}// 抽象工厂
interface UIFactory {Button createButton();TextField createTextField();
}// 具体工厂(Windows平台UI工厂)
class WindowsUIFactory implements UIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic TextField createTextField() {return new WindowsTextField();}
}// 具体工厂(MacOS平台UI工厂)
class MacOSUIFactory implements UIFactory {@Overridepublic Button createButton() {return new MacOSButton();}@Overridepublic 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.ppmy.cn/embedded/6436.html

相关文章

每日三个JAVA经典面试题(四十四)

1.什么是反应式编程?它如何优化Web应用的性能? 反应式编程是一种编程范式,它通过异步数据流的方式处理事件和数据,以实现高效的数据处理和事件驱动的程序设计。在反应式编程中,数据流可以被观察(Observabl…

Java工具类:封装Okhttp实现:Get、Post、上传/下载文件、Stream响应、代理ip

不好用请移至评论区揍我 原创代码,请勿转载,谢谢! 一、介绍 本文代码是引入Okhttp_v4.11.0,在这个基础上进行二次封装使调用方更加容易,只关注业务,而无需处理各种请求相关的重复性操作,类似文件类型请求体封装或者Form表单构造及body传参等一系列处理工具代码包括但不限…

if __name__ == ‘__main__‘ 是个什么鬼?

有句话经典的概括了这段代码的意义: “Make a script both importable and executable” 意思就是说让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行。 咋一看,其实我也不理解到底是个什么球意思,这里我们写两个…

Oracle SQL - HAVING和分析函数的执行顺序

分析函数是基于最终的结果集进行开窗的,所以HAVING比分析函数先执行 ↓ 没有HAVING时,MAX(col3) over()是A2 SQL> WITH subq_a AS2 (SELECT A col1, A1 col2, 10 col33 FROM dual4 UNION ALL5 SELECT A col1, A1 col2, -5 col36 F…

导致程序崩溃删除的地方

1. 注册日志回调函数 qInstallMessageHandler(outputMessage);解决方法 Android 环境下直接不重定向日志,经过后期调试应该是 dynamic_static 转换失败导致。 #ifndef __ANDROID__qInstallMessageHandler(outputMessage); #endif2. 单例上锁,新增了 A…

SpringBlade dict-biz/list SQL 注入漏洞复现

0x01 免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删…

接口压力测试 jmeter--入门篇(一)

一 压力测试的目的 评估系统的能力识别系统的弱点:瓶颈/弱点检查系统的隐藏的问题检验系统的稳定性和可靠性 二 性能测试指标以及测算 【虚拟用户数】:线程用户【并发数】:指在某一时间,一定数量的虚拟用户同时对系统的某个功…

人工智能的未来会怎样?Gartner发布AI技术成熟度曲线

对于任何人来说,生成式人工智能和支持它的基础模型目前都处于Gartner所谓的「膨胀预期的顶峰」,这一点并不奇怪,在最新的「Gartner AI技术成熟度曲线」中。这意味着他们正在悬崖上摇摇欲坠,这可能会使他们陷入「幻灭的低谷」。 「…