技术成神之路:设计模式(四)工厂方法模式

news/2024/7/14 21:02:09

1.定义


工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,而不是通过具体类来实例化对象。工厂方法模式的主要作用是让子类决定实例化哪一个类,从而实现对象创建的延迟到具体子类中进行。

2.主要作用


作用就是使设计更加灵活和可扩展。通过这种方式,父类无需知道具体要创建的对象是哪一种,这样就提高了系统的可扩展性和可维护性(符合开闭原则)一切优秀的模式都向设计原则看齐。

3.解决的问题

说到解决的问题,这里就不得不提下简单工厂模式了,什么?你不知道简单工厂模式是什么,没关系,先来看下定义:

简单工厂模式是一种创建型模式,它定义了一个工厂类,该类包含一个方法,根据给定的参数来返回不同类的实例。
客户端通过向工厂类传递参数来获取所需的具体对象实例,而不需要直接实例化对象。

包含角色:

  1. 工厂类(Factory):负责根据客户端的请求创建相应的对象。

  2. 产品类(Product):被创建的对象的基类或接口。具体的产品类是工厂类所创建的对象类型。

  3. 具体产品类(Concrete Product):实现了产品接口的具体对象类,由工厂类根据客户端的需求创建和返回。

UML类图:
在这里插入图片描述
代码示例:

public class LoggerFactory {public static Logger createLogger(String logType) {if ("Console".equals(logType)) {return new ConsoleLogger();} else if ("File".equals(logType)) {return new FileLogger();} else if ("Remote".equals(logType)) {return new RemoteLogger();} else {throw new IllegalArgumentException("Unsupported log type");}}
}

通过 LoggerFactory.createLogger("Console")LoggerFactory.createLogger("File") 或者 LoggerFactory.createLogger("Remote") 来获取不同类型的日志记录器,这种方式就是简单工厂模式,熟不熟悉,在你的项目中是不是也使用过这种模式呢,由于不难理解所以称为简单

简单是简单,当然他也有一些弊端,如果上面示例代码中 Logger 抽象类中只有打印一个方法,后续需要新增保存日志,过滤日志… 问题就暴露出来了,简单来说就是 简单工厂模式违反了开闭原则,即对扩展开放,对修改关闭

工厂方法模式解决了简单工厂模式的哪些问题?

  • 开闭原则:工厂方法模式遵循开闭原则,通过定义抽象工厂类和具体工厂类的继承关系,新增产品时只需增加具体工厂类和产品类,而无需修改现有代码,降低了系统的耦合性。
  • 扩展性:工厂方法模式支持更多的灵活性,每个具体的工厂类只负责创建对应的产品,符合单一职责原则,代码更加清晰和可维护。
  • 维护性:由于工厂方法模式将对象的创建延迟到子类中,避免了简单工厂模式中工厂类集中所有产品创建逻辑的问题,使代码结构更加清晰和可扩展。

简单来说,就是解决了简单工厂模式中集中创建逻辑和不符合开闭原则的问题,提高了代码的灵活性和可维护性。

4.模式原理

包含角色:

  1. 产品(Product):定义产品的接口。
  2. 具体产品(ConcreteProduct):实现产品接口的具体类。
  3. 工厂(Factory):定义创建产品对象的接口。
  4. 具体工厂(ConcreteFactory):实现创建产品对象的具体类。

UML类图:
在这里插入图片描述

// 定义产品接口
public interface Product {String operation();
}// 定义具体产品类
public class ConcreteProductA implements Product {@Overridepublic String operation() {return "产品A";}
}public class ConcreteProductB implements Product {@Overridepublic String operation() {return "产品B";}
}// 定义工厂接口
public abstract class Creator {// 工厂方法public abstract Product factoryMethod();// 其它操作方法public String someOperation() {Product product = factoryMethod();return product.operation();}
}// 定义具体工厂类
public class ConcreteCreatorA extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductA();}
}public class ConcreteCreatorB extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductB();}
}// 客户端代码
public class Client {public static void main(String[] args) {clientCode(new ConcreteCreatorA());clientCode(new ConcreteCreatorB());}public static void clientCode(Creator creator) {System.out.println("Client: " + creator.someOperation());}
}

打印:

Client: 产品A
Client: 产品B

相较简单工厂模式 增加了一个具体工厂角色,每增加一个具体产品,需要同时增加一个具体工厂类。所以说各有优缺点吧。

4.优缺点


优点:

  • 遵循开闭原则:可以在引入新产品时不修改现有代码。
  • 遵循单一职责原则:将产品对象的创建逻辑封装在工厂类中。
  • 减少代码耦合:客户端不直接依赖于具体类,只依赖于抽象产品和工厂接口(符合依赖倒置原则)。.

缺点:

  • 增加代码复杂性:每增加一个具体产品,需要同时增加一个具体工厂类。
  • 类的数量增加:每个具体产品都需要一个对应的具体工厂,会导致类的数量增加。

5.应用场景


  1. 需要创建复杂对象:当对象的创建过程比较复杂,且需要多步操作时。
  2. 产品种类多且类型不确定:当系统中需要创建的产品种类较多且类型在运行时才确定时。
  3. 需要对创建过程进行控制:当需要对对象的创建过程进行控制,并且希望将控制逻辑封装起来时。

emm… 其实还是简单工厂模式 应用场景更广泛些,毕竟简单好用🤭

总结比较:

  • 简单工厂模式适合于对象类型较少且不经常变化的场景,代码较为简单,但不符合开闭原则,难以扩展新的产品类型。
  • 工厂方法模式更加符合开闭原则,通过增加新的具体工厂和具体产品类来扩展系统功能,但会增加系统中类的个数和复杂度。

6.总结


工厂模式解决了简单工厂模式中集中创建逻辑和不符合开闭原则的问题,但同时自身也有一些弊端,但通过合理应用工厂方法模式,在特定的场景可以有效地提高系统的可维护性和扩展性。

设计模式没有最好的,只有最适合的,大家在选用时,要权衡利弊,避免过度设计!


http://www.mrgr.cn/p/18428401

相关文章

点云分割网络---Point Transformer V3

PDF:《Point Transformer V3: Simpler, Faster, Stronger》 CODE: https://github.com/Pointcept/PointTransformerV3 一、大体内容 Point Transformer V3(PTv3)没有像V2那样在注意力机制方面寻求创新,而是专注于保持点云背景下准确性和效率之间的平衡,如下所示与上一代Poin…

[图解]SysML和EA建模住宅安全系统-14-黑盒系统规约

1 00:00:02,320 --> 00:00:07,610 接下来,我们看下一步指定黑盒系统需求 2 00:00:08,790 --> 00:00:10,490 就是说,把这个系统 3 00:00:11,880 --> 00:00:15,810 我们的目标系统,ESS,看成黑盒 4 00:00:18,030 --> …

【2024_CUMCM】TOPSIS法(优劣解距离法)

目录 引入 层次分析法的局限性 简介 例子 想法1 想法2 运用实际分数进行处理 想法3 问题 扩展问题:增加指标个数 极大型指标与极小型指标 统一指标类型-指标正向化 标准化处理 计算公式 计算得分 对原公式进行变化 升级到m个指标和n个对象 代码 …

面经梳理-分布式

梳理分布式相关面经题目 请简述一下CAP理论,我们常见的中间件分别侧重点是什么?简述一下BASE理论?什么是强一致性,弱一致性,最终一致性 CAP理论 CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分…

深入理解Java并发、线程与等待通知机制

目录 一、基础概念 进程和线程 进程 线程 Java 线程的无处不在 进程间的通信 进程间通信有几种方式? CPU 核心数和线程数的关系 上下文切换(Context switch) 并行和并发 二、认识 Java 里的线程 Java 程序天生就是多线程的 线程…

【山东大学】web数据管理——复习笔记

写在前面 若有图片加载失败,请科学上网 。本文为对软件学院连老师的PPT课件总结所得的复习笔记,仅供参考。不保证对考点的全覆盖,以PPT为主。对往年考过的题相关知识点前面都标注了“考过”,并高亮,供参考。写的比较匆…

昇思14天

ResNet50图像分类 1. ResNet50图像分类概述 ResNet50是一种用于图像分类的深度卷积神经网络。图像分类是计算机视觉的基本应用,属于有监督学习范畴。ResNet50通过引入残差结构,解决了深层网络中的退化问题,使得可以训练非常深的网络。 2. …

易优CMS模板标签artpagelist瀑布流

[基础用法]标签:artpagelist 描述:实现无刷新瀑布流分页,适用于首页,列表分页,内容页等模板。小注:需配合artlist标签。 注意:要实现瀑布流分页,必须要在模板目录pc/system里创建一个模板样本,命名格式为:arclist_+tagid属性名称,比如:arclist_index001.htm,里面内…

【笔记】太久不用redis忘记怎么后台登陆了

!首先启动虚拟机linux的centos7 2.启动finalshell 我的redis启动在根目录用 redis-server redis.conf --启动 systemctl status redis --查看redis状态 是否active redis-cli -h centos的ip地址 -p 你要用的redis端口号(默认为6379) -a 你…

使用vscode远端连接虚拟机

主要是需要使用虚拟机ubuntu上的cmake环境,但是为了GUI又不想搞WSL,在虚拟机上再装一个vscode又有点卡,所以用了这招。 基本上网上的方法照着来就行了。几个简单的小步骤稍微记录一下。给虚拟机安装一下openssh并修改配置开放22端口(就很简单的跟着[1]来就行了)虚拟机ifco…

程序员学长 | PyCaret,一个超强的 python 库

本文来源公众号“程序员学长”,仅用于学术分享,侵权删,干货满满。 原文链接:PyCaret,一个超强的 python 库 今天给大家分享一个超强的 python 库,PyCaret。 https://github.com/pycaret/pycaret 简介 …

禁用windows的语音识别快捷键win+ctrl+s

win11组合键winctrls会弹出语音识别提示,即使到设置里禁用了语音识别也没用 解决办法:安装PowerToys,通过“键盘管理器”-“重新映射快捷键”禁用 PowerToys是微软自己的工具,不用担心安全问题,下载地址:h…

基于Transformer的端到端的目标检测 | 读论文

本文正在参加 人工智能创作者扶持计划 提及到计算机视觉的目标检测,我们一般会最先想到卷积神经网络(CNN),因为这算是目标检测领域的开山之作了,在很长的一段时间里人们都折服于卷积神经网络在图像处理领域的优势&…

Python 数据挖掘

数据挖掘基础数据挖掘:这种从数据中“淘金”,从大量数据(包括文本)中挖掘出隐含的、未知的、对决策有潜在价值的关系、模式和趋势,并用这些知识和规则建立用于决策支持的模型,提供预测性决策支持的方法、工具和过程,就是数据挖掘;它是利用各种分析工具在大量数据中寻找其规…

Python Selenium+cookie+XPATH爬取数据

以某科研基金信息平台为例,写了一个基于selenium的web自动化爬虫。不带验证码防反爬以及代理ip池,是最基础的自动化工具爬虫。 一、首先,此平台需要登录后才能正常访问,否则数据不全,因此需要登录后获取cookie,以便selenium能够以登录状态运行 1.F12打开开发者工具,找到…

Postman使用教程【项目实战】

目录 引言软件下载及安装项目开发流程1. 创建项目2. 创建集合(理解为:功能模块)3. 设置环境变量,4. 创建请求5. 测试脚本6. 响应分析7. 共享与协作 结语 引言 Postman 是一款功能强大的 API 开发工具,它可以帮助开发者测试、开发和调试 API。…

个人赛补题

round 1范围很小用暴力+贪心,左右枚举,先拿再放。尽量放小的所以需要排下序 include include "map" include "algorithm" include "cmath" include "vector" include "set" include "queue" define int long lo…

Linux驱动开发-03字符设备驱动框架搭建

一、字符设备驱动开发步骤 驱动模块的加载和卸载(将驱动编译模块,insmod加载驱动运行)字符设备注册与注销(我们的驱动实际上是去操作底层的硬件,所以需要向系统注册一个设备,告诉Linux系统,我有…

【React】基础数据回填--useForm与setFieldsValue详解

相关属性 1.form 2.setFieldsValue 代码 import{Form }from"antd";const Publish =