工厂方法设计模式是什么?什么是 Factory Method 工厂方法设计模式?Python 工厂方法设计模式示例代码

什么是 Factory Method 工厂方法设计模式?

工厂方法(Factory Method)是一种创建型设计模式,它定义了一个创建对象的接口,但将实际的实例化工作延迟到子类中。这样,可以使一个类的实例化延迟到其子类,让子类决定实例化哪个类。

在这里插入图片描述

主要角色:

  1. 抽象产品(Product): 定义了产品的抽象类或接口,是工厂方法创建的对象的共同接口。

  2. 具体产品(Concrete Product): 实现了抽象产品接口的具体对象。

  3. 抽象工厂(Creator): 声明了创建产品对象的工厂方法,是工厂方法模式的核心,也可以是一个抽象类或接口。

  4. 具体工厂(Concrete Creator): 实现了抽象工厂中的工厂方法,负责创建具体的产品对象。

在这里插入图片描述

工作流程:

  1. 定义抽象产品: 创建一个产品接口或抽象类,声明产品的共同方法。

  2. 实现具体产品: 创建具体的产品类,实现抽象产品接口。

  3. 定义抽象工厂: 声明一个抽象工厂类,其中包含一个工厂方法用于创建产品。

  4. 实现具体工厂: 实现抽象工厂中的工厂方法,根据需求创建具体的产品对象。

  5. 客户端使用工厂方法: 客户端通过调用具体工厂的工厂方法来创建产品,不直接与具体产品类耦合。

优点:

  1. 符合开闭原则: 工厂方法模式通过抽象工厂和具体工厂的分离,使得增加新产品类型更容易,符合开闭原则,不需要修改现有代码。

  2. 降低耦合度: 客户端代码与具体产品的实现解耦,只依赖于抽象工厂和抽象产品,提高了系统的灵活性。

  3. 可扩展性高: 可以很容易地添加新的产品类型,只需要增加对应的具体工厂类和产品类,无需修改其他现有代码。

  4. 可维护性强: 因为每个具体产品的创建逻辑都在各自的具体工厂类中,使得代码的维护更加方便。

缺点:

  1. 类的数量增加: 随着产品类型的增加,可能会导致具体工厂和产品类的数量激增,使得类的数量增加。

  2. 增加了系统复杂性: 引入了更多的抽象和接口,可能会增加系统的复杂性和理解难度,增加了代码的抽象层次。

  3. 不适用于简单情景: 如果产品类型较少,而且不需要频繁增加新的产品类型,使用工厂方法可能显得繁琐,不划算。

  4. 创建实例开销: 在创建大量对象时,可能会增加额外的开销,因为需要通过工厂来创建对象。

总体来说,工厂方法模式适用于需要创建多种类型对象、需要灵活扩展、需要降低系统耦合度的场景,但在简单情景下使用可能会增加不必要的复杂性。在实际应用中需要根据具体情况选择是否使用该模式。


Python 实现工厂方法设计模式示例代码(一):

假设有一个简单的图表库,可以创建不同类型的图表(柱状图、折线图等)并绘制。这里使用工厂方法模式创建不同类型的图表。

from abc import ABC, abstractmethod

# 抽象产品 - 图表
class Chart(ABC):
    @abstractmethod
    def draw(self):
        pass

# 具体产品 - 柱状图
class BarChart(Chart):
    def draw(self):
        print("Drawing bar chart")

# 具体产品 - 折线图
class LineChart(Chart):
    def draw(self):
        print("Drawing line chart")

# 抽象工厂
class ChartFactory(ABC):
    @abstractmethod
    def create_chart(self) -> Chart:
        pass

# 具体工厂 - 创建柱状图
class BarChartFactory(ChartFactory):
    def create_chart(self) -> Chart:
        return BarChart()

# 具体工厂 - 创建折线图
class LineChartFactory(ChartFactory):
    def create_chart(self) -> Chart:
        return LineChart()

if __name__ == "__main__":
    # 客户端
    bar_factory = BarChartFactory()
    bar_chart = bar_factory.create_chart()
    bar_chart.draw()  # 输出:Drawing bar chart

    line_factory = LineChartFactory()
    line_chart = line_factory.create_chart()
    line_chart.draw()  # 输出:Drawing line chart

在这个示例中,Chart 是抽象产品接口,定义了图表的绘制方法。BarChartLineChart 是具体产品类,分别表示柱状图和折线图。ChartFactory 是抽象工厂接口,包含了一个创建图表的抽象方法。BarChartFactoryLineChartFactory 是具体工厂类,分别实现了创建柱状图和折线图的工厂方法。客户端通过具体工厂的工厂方法来创建特定类型的图表。


Python 实现工厂方法设计模式示例代码(二):

假设你正在开发一个游戏,需要不同的工厂来创建不同类型的武器。这里使用工厂方法模式来创建不同类型的武器。

from abc import ABC, abstractmethod

# 抽象产品 - 武器
class Weapon(ABC):
    @abstractmethod
    def attack(self):
        pass

# 具体产品 - 刀
class Knife(Weapon):
    def attack(self):
        print("Using knife to attack")

# 具体产品 - 枪
class Gun(Weapon):
    def attack(self):
        print("Using gun to attack")

# 抽象工厂
class WeaponFactory(ABC):
    @abstractmethod
    def create_weapon(self) -> Weapon:
        pass

# 具体工厂 - 创建刀
class KnifeFactory(WeaponFactory):
    def create_weapon(self) -> Weapon:
        return Knife()

# 具体工厂 - 创建枪
class GunFactory(WeaponFactory):
    def create_weapon(self) -> Weapon:
        return Gun()

if __name__ == "__main__":
    # 客户端
    knife_factory = KnifeFactory()
    knife = knife_factory.create_weapon()
    knife.attack()  # 输出:Using knife to attack

    gun_factory = GunFactory()
    gun = gun_factory.create_weapon()
    gun.attack()  # 输出:Using gun to attack

这个示例模拟了游戏中不同类型武器的创建。Weapon 是抽象产品,定义了武器的攻击方法。KnifeGun 是具体产品类,分别表示刀和枪。WeaponFactory 是抽象工厂接口,包含了一个创建武器的抽象方法。KnifeFactoryGunFactory 是具体工厂类,分别实现了创建刀和枪的工厂方法。客户端通过具体工厂的工厂方法来创建特定类型的武器。


使用工厂方法设计模式时,需要注意哪些地方?

在使用工厂方法设计模式时,需要注意以下几个方面:

  1. 扩展性: 工厂方法模式是为了解决创建对象的问题,要确保系统具有良好的扩展性,能够方便地添加新的产品类型或工厂。

  2. 产品族和产品等级结构: 要根据实际需求合理设计产品族和产品等级结构,确保抽象工厂和产品的设计符合业务逻辑。

  3. 单一职责原则: 每个具体工厂类应该只负责创建一种产品,符合单一职责原则,避免一个工厂类负责过多产品的创建。

  4. 依赖倒置原则: 针对抽象类型编程,依赖于接口而不是具体实现,确保客户端代码与具体产品类解耦。

  5. 合理命名: 工厂方法、产品类、工厂类的命名应该清晰易懂,能够清晰表达其作用和职责。

  6. 考虑性能: 在创建大量对象时,工厂方法可能会增加额外的开销,需要考虑其对性能的影响。

  7. 设计模式选择: 工厂方法模式并不是适用于所有场景的最佳解决方案,需要根据实际情况选择合适的设计模式。

  8. 遵循设计原则: 保持设计模式的灵活性和简洁性,遵循设计原则,避免过度设计。

总的来说,使用工厂方法模式时需要考虑扩展性、结构设计、原则遵循以及性能等方面的问题,合理设计和组织工厂结构,确保系统易于扩展和维护。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

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

相关文章

Laravel 安装(笔记一)

目录 第一步、Laravel 一般使用 composer安装 第二步、使用composer安装项目 第三步、配置环境 第四步、访问域名,安装完成 Laravel 官网 l​​​​​​​Installation - Laravel 中文网 为 Web 工匠创造的 PHP 框架 第一步、Laravel 一般使用 composer安装 如…

2023 年最新 MySQL 数据库 Windows 本地安装、Centos 服务器安装详细教程

MySQL 基本概述 MySQL是一个流行的关系型数据库管理系统(RDBMS),广泛应用于各种业务场景。它是由瑞典MySQL AB公司开发,后来被Sun Microsystems收购,最终被甲骨文公司(Oracle Corporation)收购…

西门子S7-200SMART常见通讯问题解答

1台200SMART 如何控制2台步进电机? S7-200SMART CPU最多可输出3路高速脉冲(除ST20外),这意味着可同时控制最多3个步进电机,通过运动向导可配置相应的运动控制子程序,然后通过调用子程序编程可实现对步进电…

硬核神作|万字带速通Nacos

目录 Nacos注册中心 基本介绍 概述 特性 服务注册中心 (Service Registry) Nacos服务分级存储模型 Nacos权重配置 Nacos环境隔离 Nacos与Eureka的区别 Java代码实战 实战架构 父工程pom文件 student-service服务 teacher-service服务 测试 Nacos配置管理 基本…

【开源】基于Vue和SpringBoot的创意工坊双创管理系统

项目编号: S 049 ,文末获取源码。 \color{red}{项目编号:S049,文末获取源码。} 项目编号:S049,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、…

Tomcat实现WebSocket即时通讯 Java实现WebSocket的两种方式

HTTP协议是“请求-响应”模式,浏览器必须先发请求给服务器,服务器才会响应该请求。即服务器不会主动发送数据给浏览器。 实时性要求高的应用,如在线游戏、股票实时报价和在线协同编辑等,浏览器需实时显示服务器的最新数据&#x…

这些仪表板常用的数据分析模型,你都见过吗?

本文由葡萄城技术团队发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 ##前言 在数字化时代,数据已经成为了企业决策和管理的重要依据。而仪表板作为一种数据可视化工具&#x…

【Azure 架构师学习笔记】-Azure Storage Account(7)- 权限控制

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Storage Account】系列。 接上文 【Azure 架构师学习笔记】-Azure Storage Account(6)- File Layer 前言 存储帐户作为其中一个数据终端存储,对安全性的要求非常高,不管…

geemap学习笔记011:可视化遥感影像随时间的变化

前言 本节主要是介绍 .ts_inspector 工具,它是可以可视化遥感影像随时间的变化,与先前文章中介绍的.split_map差别在于,它可以加载时间序列数据。 1 导入库 !pip install geemap #安装geemap库 import ee import geemapgeemap.show_youtub…

了解一下公网IP和域名的区别与联系

​  公网IP和域名是互联网中两个重要的概念,它们在网络通信和网站访问中起着不同的作用。 我们来了解一下公网IP。公网IP是指在全球范围内唯一的IP地址,用于标识互联网上的设备。每个设备连接到互联网时都会被分配一个公网IP地址,这个地址可…

Python批量备份交换机配置+自动巡检

自动巡检功能考虑到不同设备回显有所不同,需要大量正则匹配,暂时没时间搞这些,所以索性将命令回显全部显示,没做进一步的回显提取。 以下是程序运行示例:#自动备份配置: 备份完成后,将配置保存于…

UVM项目笔记——通过寄存器模型实现AHB接口的寄存器读写(内含源码)

目录 1.前言 2.DRIVER实现 2.1 AHB二级流水时序 2.2 “队列错位法”实现driver 2.3 driver代码 2.4 仿真log与波形 2.5 多级流水拓展方法 1.前言 UVM driver在接口协议的实现中起着非常重要的作用,因为它一端处理基于类的事务级sequence,另一端处…

如何用 GPTs 帮你写科研项目申请书?

(注:本文为小报童精选文章,已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费) 需求 学生们往往会觉得,写开题报告是个苦差事。但他们或许不知道,老师们写起科研项目申请书,压力远比他们…

Linux常用命令——bmodinfo命令

在线Linux命令查询工具 bmodinfo 显示给定模块的详细信息 补充说明 bmodinfo命令用于显示给定模块的详细信息。 语法 bmodinfo(选项)(参数)选项 -a:显示模块作者; -d:显示模块的描述信息; -l:显示模块的许可信息…

第三方模块远程注入到软件中引发软件异常的若干实战案例分享

目录 1、概述 2、老版本的输入法导致软件CPU频繁跳高(导致软件出现卡顿)的问题 3、QQ拼音输入法注入到安装包进程中,导致安装包主线程卡死问题 3.1、多线程死锁分析 3.2、进一步研究 4、安全软件注入到软件中,注入模块发生了…

Xilinx Zynq-7000系列FPGA任意尺寸图像缩放,提供两套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐FPGA图像处理方案FPGA图像缩放方案 3、设计思路详解HLS 图像缩放介绍 4、工程代码1:图像缩放 HDMI 输出PL 端 FPGA 逻辑设计PS 端 SDK 软件设计 5、工程代码2:图像缩放 LCD 输出PL 端 FPGA 逻辑设计PS 端 SDK 软件设…

uni-app - 日期 · 时间选择器

目录 1.基本介绍 2.案例介绍 ①注意事项: ②效果展示 3.代码展示 ①view部分 ②js部分 ③css样式 1.基本介绍 从底部弹起的滚动选择器。支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器&a…

visionOS空间计算实战开发教程Day 4 初识ImmersiveSpace

细心的读者会发现在在​​Day1​​​和​​Day2​​​的示例中我们使用的都是​​WindowGroup​​。 main struct visionOSDemoApp: App {var body: some Scene {WindowGroup {ContentView()}} } 本节我们来认识在visionOS开发中会经常用到的另一个概念​​ImmersiveSpace​​…

如何看待Unity新收费模式?

Unity新收费模式的变化主要在于将收费重心从功能分级收费转变为资源使用量收费,这个改变已经引起了一定的争议和反响。以下是我个人的看法: 优点: 更公平的收费方式:新的收费模式将更加公平,用户只需按照实际使用的数…

css取消移动端长按元素背景色

在开发微信小程序的时候,发现有的元素长按之后,出现了讨厌人的背景色,这就很奇怪,就想把它去掉,所以这里教一下方法: 在所在元素添加css样式: // 取消长按的背景色-webkit-tap-highlight-color:…