工厂模式:没你想像的那么难

news2025/1/12 15:47:10

工厂模式

工厂模式是一种创建型设计模式,它允许创建对象而无需指定将要创建的对象的具体类。它通过将对象的创建委托给一个单独的方法或类来完成,从而隐藏了对象的实例化逻辑。这样可以提高代码的灵活性,减少了代码中的重复和耦合。

在工厂模式中通常会包含以下几个要素:

  • 产品接口(Product Interface):定义了要创建的对象的通用接口。
  • 具体产品(Concrete Product):实现了产品接口的具体对象。
  • 工厂接口(Factory Interface):定义了一个创建对象的方法,通常是一个接口或者抽象类。
  • 具体工厂(Concrete Factory):实现了工厂接口,负责创建具体产品的对象。

现在,让我们通过一个 Python 示例来说明工厂模式的用法。假设我们有一个简单的图形绘制应用,它可以绘制圆形和矩形。我们将使用工厂模式来创建这些形状对象。

# 产品接口:形状
class Shape:
    def draw(self):
        pass

# 具体产品:圆形
class Circle(Shape):
    def draw(self):
        print("Inside Circle::draw() method.")

# 具体产品:矩形
class Rectangle(Shape):
    def draw(self):
        print("Inside Rectangle::draw() method.")

# 工厂接口
class ShapeFactory:
    def create_shape(self, shape_type):
        pass

# 具体工厂:形状工厂
class SimpleShapeFactory(ShapeFactory):
    def create_shape(self, shape_type):
        if shape_type.lower() == "circle":
            return Circle()
        elif shape_type.lower() == "rectangle":
            return Rectangle()
        else:
            raise ValueError("Unsupported shape type: " + shape_type)

# 客户端代码
if __name__ == "__main__":
    # 创建形状工厂对象
    shape_factory = SimpleShapeFactory()

    # 根据工厂创建形状对象
    circle = shape_factory.create_shape("circle")
    circle.draw()

    rectangle = shape_factory.create_shape("rectangle")
    rectangle.draw()

在这个示例中,我们定义了 Shape 接口作为产品接口,然后实现了具体的产品类 Circle 和 Rectangle。接着,我们定义了一个工厂接口 ShapeFactory 和一个具体工厂类 SimpleShapeFactory,后者实现了创建形状对象的方法 create_shape。最后,在客户端代码中,我们使用工厂对象来创建具体的形状对象,而无需直接实例化具体的产品类。

这种设计使得客户端代码与具体的产品类解耦,使得在需要添加新的产品类型时,只需要修改工厂类而无需修改客户端代码,从而提高了代码的可维护性和可扩展性。

抽象工厂模式

抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或依赖对象的方法,而无需指定其具体类。该模式通过引入抽象工厂和具体工厂来实现,从而使得客户端代码与具体产品类的实现相互独立。

抽象工厂模式通常涉及以下几个关键组件:

  • 抽象工厂(Abstract Factory):定义了一组方法,用于创建一系列相关或依赖对象的抽象接口。
  • 具体工厂(Concrete Factory):实现了抽象工厂接口,并负责创建具体产品族的对象。
  • 抽象产品(Abstract Product):定义了一组相关或依赖对象的抽象接口。
  • 具体产品(Concrete Product):实现了抽象产品接口的具体对象。

抽象工厂模式与工厂模式相比,其可以创建一组相关的对象,而不仅仅是单个对象。

下面是一个简单的 Python 示例,演示了抽象工厂模式的应用。假设我们有一个图形界面库,它包含按钮和文本框两种组件,我们可以根据不同的操作系统(例如 Windows 和 macOS)创建对应的按钮和文本框。

# 抽象产品:按钮接口
class Button:
    def paint(self):
        pass

# 具体产品:Windows 按钮
class WindowsButton(Button):
    def paint(self):
        print("Rendering a Windows style button.")

# 具体产品:macOS 按钮
class MacOSButton(Button):
    def paint(self):
        print("Rendering a macOS style button.")

# 抽象产品:文本框接口
class TextBox:
    def paint(self):
        pass

# 具体产品:Windows 文本框
class WindowsTextBox(TextBox):
    def paint(self):
        print("Rendering a Windows style text box.")

# 具体产品:macOS 文本框
class MacOSTextBox(TextBox):
    def paint(self):
        print("Rendering a macOS style text box.")

# 抽象工厂:UI 工厂接口
class UIFactory:
    def create_button(self):
        pass

    def create_text_box(self):
        pass

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

    def create_text_box(self):
        return WindowsTextBox()

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

    def create_text_box(self):
        return MacOSTextBox()

# 客户端代码
if __name__ == "__main__":
    # 根据当前操作系统选择对应的 UI 工厂
    os = "windows"  # 可以根据实际情况修改
    if os.lower() == "windows":
        ui_factory = WindowsUIFactory()
    elif os.lower() == "macos":
        ui_factory = MacOSUIFactory()
    else:
        raise ValueError("Unsupported operating system: " + os)

    # 使用 UI 工厂创建按钮和文本框
    button = ui_factory.create_button()
    text_box = ui_factory.create_text_box()

    # 渲染按钮和文本框
    button.paint()
    text_box.paint()

在这个示例中,我们定义了抽象产品接口 Button 和 TextBox,以及两种具体产品类(Windows 和 macOS 版本)。然后,我们定义了抽象工厂接口 UIFactory 和两个具体工厂类(WindowsUIFactory 和 MacOSUIFactory),分别用于创建 Windows 和 macOS 版本的按钮和文本框。最后,在客户端代码中,我们根据当前操作系统选择对应的工厂,并使用工厂创建按钮和文本框,然后调用它们的渲染方法。

 查看原文:工厂模式:没你想像的那么难

关注公众号 "字节航海家" 及时获取最新内容

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

社会底层人民要被人工智能和机器人淘汰了吗?你害怕被AI代替吗?

随着科技的飞速发展,人工智能和机器人技术已经成为我们日常生活中不可或缺的一部分。这些技术的广泛应用引发了一些担忧,其中之一就是社会底层人民是否会被人工智能和机器人所淘汰。然而,这个问题并不是非黑即白的,它需要从多个角…

excel导出标准化

虽然标题叫标准化,只不过是我自己的习惯,当一件事情变得流程标准化之后,开发程序就会飞快,开发评估工作总是 搞个1~2天,实则前端后端一起开发,1个小时就可以搞定。 1 前端 const exportXls async () >…

2024环境工程、能源系统与化学材料国际会议(ICEEESCM 2024)

2024环境工程、能源系统与化学材料国际会议(ICEEESCM 2024) 一、【会议简介】 2024环境工程、能源系统与化学材料国际会议(ICEEESCM 2024)将于2024年在西安举行。会议将围绕环境工程、能源系统与化学材料等议题展开讨论,旨在为从事环境工程…

省赛模板构建——ADC

一般考试只考一个滑动变阻器,考R37的比较多 打开STM32CubeMX 四步配置 配置PB12对应R38的ADC1_IN11,配置PB15对应R37的ADC2_IN15 把通道11设置为单通道 时钟分频为异步/2(对应ADC的时钟来源),异步一般都选2 配置最大采样周期为640.5 配置A…

Nacos进阶

目录 Nacos支持三种配置加载方案 Namespace方案 DataID方案 Group方案 同时加载多个配置集 Nacos支持三种配置加载方案 Nacos支持“Namespacegroupdata ID”的配置解决方案。 详情见:Nacos config alibaba/spring-cloud-alibaba Wiki GitHub Namespace方案…

vue实现自定义树形穿梭框功能

需求: 我们在开发过程中,会遇到需要将一个数据选择做成穿梭框,但是要求穿梭框左侧为树形结构、右侧为无层级结构的数据展示,ElementUI自身无法在穿梭框中添加树形结构,网上搜到了大佬封装的插件但是对于右侧的无树形结…

three.js 叉乘判断物体在人前左,前右,后左、后右

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs"></div><div style"padding: 10px;text-align: left;">叉乘判断物体…

Flutter修改了函数申明后hotload会失效

文章目录 问题描述问题原因解决方法 问题描述 在 Flutter 开发中&#xff0c;如果修改了函数的声明&#xff0c;Hot Reload 功能通常不能正常使用&#xff0c;需要重新编译。 问题原因 Hot Reload 功能的工作原理是通过注入新的 Dart 代码来更新运行中的应用程序。当您修改函…

从零学算法289

289.根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即为 活细胞 …

全面评估2023年最受欢迎的 3 类型原型设计工具

与其他设计工具相比&#xff0c;原型设计工具往往强调快速设计&#xff0c;界面建设和交互设计可以通过预设的组件、模板等内容快速完成。这可以在短时间内呈现和表达这个想法。 在原型设计工具市场上&#xff0c;有遥遥领先的基准产品、积累的新兴产品、没有创新的模仿产品、…

Tomcat布署及优化-----JDK和Tomcat

1.Tomcat简介 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器&#xff0c;Tomcat 属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试 JSP 程序的首选。一般来说&…

Springboot项目集成短信验证码(超简单)

操作流程 注册验证码平台创建验证码模版开始集成&#xff08;无需引入第三方库&#xff09; 注册并登陆中昱维信验证码平台 获取AppID和AppKey。 创建验证码模版 创建验证码模版&#xff0c;获取验证码模版id 开始集成 创建controller import org.springframework.web.bi…

YOLOv8涨点技巧,添加SE注意力机制提升目标检测效果

目录 论文地址 摘要 SE结构图 代码实现 Squeeze Excitation SE-Inception and SE-ResNet yaml文件编写 完整代码分享 总结 论文地址 http://openaccess.thecvf.com/content_cvpr_2018/papers/Hu_Squeeze-and-Excitation_Networks_CVPR_2018_paper.pdf 摘要 卷积神…

day06_菜单管理(查询菜单,添加菜单,添加子菜单,修改菜单,删除菜单,角色分配菜单,查询菜单,保存菜单,动态菜单)

文章目录 1 菜单管理1.1 表结构介绍1.2 查询菜单1.2.1 需求说明1.2.2 页面制作1.2.3 后端接口SysMenuSysMenuControllerSysMenuServiceMenuHelperSysMenuMapperSysMenuMapper.xml 1.2.4 前端对接sysMenu.jssysMenu.vue 1.3 添加菜单1.3.1 需求说明1.3.3 页面制作1.3.3 后端接口…

续上一篇---Jetson Xavier NX 开发板Yolov4 环境搭建和摄像头实时检测教程

1.已成功安装完CUDA&#xff0c;OpenCV&#xff0c;cuDNN&#xff0c;配置如下&#xff1a; 2.下载yolov4 自行去GitHub下载&#xff0c;然后再导入NX中&#xff0c;这样比较快且不容易出错。 https://github.com/AlexeyAB/darknet.git 3.配置 下载好包后解压缩&#xff0c;进…

一个完整的Flutter项目的基本构成

目录 1.页面跳转2.本地数据库和读取2.1 在pubspec.yaml中添加数据库框架依赖2.2 创建db.dart 初始化数据库并创建表2.3 安装JsonToDart插件2.4 创建实体类 user_bean.dart2.5 增删改查&#xff1a; 3.网络请求数据解析UI渲染 本篇主要总结下一个完整的Flutter项目有哪些基本构成…

C语言第三十三弹---动态内存管理(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、为什么要有动态内存分配 2、malloc和free 2.1、malloc 2.2、free 3、calloc和realloc 3.1、calloc 3.2、realloc 4、常见的动态内存的错…

【单片机学习的准备】

文章目录 前言一、找一个视频是二、画图软件三、装keil5 仿真protues总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 项目需要&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、找一个视频是 https://www.b…

mariadb数据库——安装,创建数据库

MariaDB是一个流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是MySQL的一个分支。 安装 apt -y install mariadb-servervi /etc/mysql/mariadb.conf.d/50-server.cnf character-set-server utf8mb4 collation-server utf8mb4_general_c…

让AI给你写代码,初体验(三)- AI加上格式化对话,实现对单个文件的修改/保存

上一篇中&#xff0c;AI生成web应用初步解决了简单web应用生成&#xff0c;但是存在两方面的问题 1&#xff09; 无法向AI提供增量需求&#xff0c;特别是一个对话结束之后&#xff0c;只能把全部需求&#xff08;包括新需求&#xff09;再描述一遍 2&#xff09; 无法用AI对存…