工厂设计模式总结

一、简单工厂

1.1 概述

背景: 代码中存在根据不同条件创建不同对象的场景。例如:

if ("json".equals(name)) {return new JsonConfigParser();
} else if ("xml".equals(name)) {return new XmlConfigParser();
} else if ("yaml".equals(name)) {return new YamlConfigParser();
}

存在的问题:

  • 当需要增加新的对象时,需要直接修改代码,违背了开闭原则;
  • 对象的创建和使用耦合在一块,耦合性强,违背了面向接口编程;
  • 创建和使用在同一个方法中,违背了方法的单一职责原则,若方法逻辑复杂,则会导致可读性下降

解决方案: 使用简单工厂。抽象出一个Factory类,负责对象的创建,并提供给外部使用的方法。

1.2 定义

 提供一个创建对象实例的功能,而无需关心其具体实现。被创建实例的类型可以是接口、抽象类或普通类。

1.3实现方案

多例场景下:所有对象抽象出一层Factory对象,但中间的if…else逻辑没有去掉,修改时违背了开闭原则;
单例场景:使用Map提前缓存单例对象。

1.4 优缺点

优点:

1. 封装性好。对创建对象的行为封装了一层Factory类,实现了面向接口编程;
2. 松耦合。将对象创建和使用解耦,实现了松耦合;
3. 可维护性好。将创建对象的行为统一到Factory类中,实现【一处修改,多处联动】,维护性大大提高;
4. 符合单一职责。将创建对象的行为放到Factory类中,实现了Factory类的职责单一。

缺点:

1. 客户端需要知道传入的参数是什么含义,才能准确创建对象,增加了复杂度;
2. 若需要新增加对象的类型,需要修改Factory类中的if..else逻辑,违背了开闭原则

二、工厂方法

2.1 背景

主要解决:简单工厂模式下的多例场景中的if…else问题,使修改代码符合开闭原则。

2.2 定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类中。

2.3 实现方案

方案1:使用多态的方式,针对每一个对象,单独创建一个工厂类,但是在使用端又引入了if…else来判断使用哪个Factory类
优化方案:Factory一般场景下是单例的,考虑使用Map来进行缓存【SpringBoot中可以使用@PostConstuct注解实现无缝注入】

2.4 优缺点

优点:

1. 符合开闭原则

缺点:

1. 增加了类的个数,降低了可读性

三、抽象工厂

背景: 简单工厂和工厂方法解决的是单一维度的分类方式。比如按照颜色给水果进行分类,但是若新增分类方式,按照品种进行分类,则需要创建一倍的工厂对象,增加了系统复杂度。
解决方案: 一个工厂对象可以创建不同类型的对象,可以有效降低工厂对象的个数。

四、三种实现方式的应用场景

4.1 按照维度来区分

单一维度:采用简单工厂或工厂方法模式
多维度:采用抽象工厂模式

4.2 简单工厂和工厂方法模式区分

  1. 如果每个Factory仅做简单的new对象操作,会导致Factory层非常薄,考虑采用简单工厂方式
  2. 若创建对象的逻辑比较复杂,比如中间要组合其他类对象,做各种初始化操作的时候,考虑采用工厂方法模式

某些场景下: 如果对象不可复用,那工厂类每次都要返回不同的对象。如果我们使用简单工厂模式来实现,就只能选择第一种包含 if 分支逻辑的实现方式。如果我们还想避免烦人的 if-else 分支逻辑,这个时候,我们就推荐使用工厂方法模式

五、收获

  1. 封装变化】:要识别出【稳定点和非稳定点】,将非稳定点进行约束,即要考虑扩展,使用设计模式进行优化。比如工厂模式,稳定点是调用方使用方式,非稳定点是对象的创建逻辑,因此,将创建逻辑给抽取出来
  2. 代码复用】:项目中很多地方使用相同的逻辑,那么需要抽取通用的逻辑出来进行封装。比如工厂模式,创建对象的动作可能散落在各个地方,使用工厂模式可以统一管理,达到代码复用;
  3. 隔离复杂性】:将复杂的逻辑封装起来,调用者可以不关系复杂逻辑的过程;
  4. 控制复杂度】:将复杂的逻辑抽离出来,让原本的函数职责更加单一,代码更加简洁。比如工厂模式,将创建逻辑抽取到Factory类中

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

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

相关文章

邀请函 | 2024年数据技术嘉年华集结号已吹响,期待您参会!

龙腾四海内,风云际会时,2024年中国数据嘉年华如约而至。从起初小范围的网友聚会,到如今面向全国各地从业者、爱好者的年度集会,纵使岁月更迭,我们初心依旧。我们在各自最好的年华里共同见证了中国数据库行业的蓬勃发展…

Linux下的IO多路复用

文章目录 一. IO的概念和分类1. IO操作的原理:二. I/O多路复用使用场景和作用1. 问题: 一台网络服务器需要接收100台客户端的连接和数据通信,应该如何设计和实现?2. I/O多路复用机制: 三. Select poll epollselectpoll…

【前端素材】推荐优质后台管理系统Modernize平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理和控制网站、应用程序或系统后台操作的软件工具,通常由授权用户(如管理员、编辑人员等)使用。它提供了一种用户友好的方式来管理网站或应用程序的内容、用户、数据等方面的操作,并且通常…

光学3D表面轮廓仪微纳米三维形貌一键测量

光学3D表面轮廓仪(白光干涉仪)利用白光干涉原理,以0.1nm分辨率精准捕捉物体的表面细节,实现三维显微成像测量,被广泛应用于材料学领域的研究和应用。 了解工作原理与技术 材料学领域中的光学3D表面轮廓仪,也被称为白光干涉仪&am…

Mybatis框架相关问题(面试)

目录 1、什么是Mybatis? 2、Mybatis的优点 3、Mybatis的缺点 4、Mybatis框架的适用场合 5、#{}和${}的区别是什么 {}是预编译处理,${}是字符串替换。 6、实体类中的属性名和表中的字段名不一样,怎么办? 8、编写模糊查询like语句 9、…

【LV14 day9内核模块编译】

模块三要素: 入口函数 出口函数 module_license 一、内核模块基础代码解析 Linux内核的插件机制——内核模块 类似于浏览器、eclipse这些软件的插件开发,Linux提供了一种可以向正在运行的内核中插入新的代码段、在代码段不需要继续运行时也可以从内核…

常用的集合有哪些

常用的三大类集合:Set、List、Map。 1 Set 1) Set 集合属于单列集合,不允许包含重复元素; 2) 判断元素是否重复的标准为对象的 equals 方法,存在时返回 false,不存在返回 true; 3) 元素的排序规则,由相应的实现类决定,分为无序、元素大小排序、写入顺序排序; 4) 初始化…

SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton 在继续深入探讨 SmartInitializingSingleton接口之前,让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE(Java Enterprise Edition)全栈(full-stack&#x…

力扣 724. 寻找数组的中心下标

思路: 创建两个变量sum和sum1,sum代表左边元素的和,sum1代表右边元素的和 然后假设从数组下标0开始,一直到最后一个作为中心下标 如果sumsum1,返回此时的中心下标 如果所有下标循环完了,发现没有return…

Apipost 数据模型功能API数据重复利用起来

在Apipost数据模型中用户可以预先创建多个数据模型,并在API设计过程中重复利用这些模型来构建API 创建数据模型 在左侧导航点击「数据模型」-「新建数据模型」在右侧工作台配置数据模型参数 引入数据模型 在API设计预定义响应期望下点击引用数据模型,…

Docker安装与基础知识

目录 -----------------Docker 概述--------------------------- 容器化越来越受欢迎,因为容器是: Docker与虚拟机的区别: Docker核心概念: ●镜像 ●容器 ●仓库 -----------------安装 Docker--------------------------…

操作系统——处理机调度

文章目录 进程调度0.概念1.调度分类高级调度低级调度中级调度七状态模型调度对比 2.进程调度进程调度的时机进程调度的方式进程的切换方式调度器/调度程序闲逛进程 3. 调度算法的评价指标CPU利用率系统吞吐量周转时间等待时间响应时间 4. 调度算法先来先服务(FCFS)短作业优先(S…

django rest framework 学习笔记-实战商城3

01用户模块模型定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记 用户模块及商品数据表结构设计 from ckeditor.fields import RichTextField # pip install django-ckeditor from django.db import models# Create your models here. # from wx.richtext import Ri…

MATLAB环境下基于PSO-DBN-ELM方法的图像分类

在纯数据驱动的图像识别方法中,深度信念网络DBN识别模型具备较好的识别性能。对于DBN模型而言,可利用的数据越多,挖掘的信息也越多,建立的模型就越准确。然而DBN本身仍存在一定的不足之处,一方面由于DBN内部包含多层限…

servlet---->request.getHeader(“X-Requested-With“);有什么作用?

X-Requested-With 是一个自定义的HTTP请求头,主要用于在服务器端识别请求是由Ajax技术发起的还是由其他技术发起的。这个请求头是由浏览器或客户端应用程序添加的,因此其值可能取决于发送请求的客户端或者开发者的选择。 如果请求不是通过JavaScript的 …

微信小程序支付(前后端都包含)

Java中换取微信支付唯一订单号(用于换取支付窗口) /*** 微信小程序支付*/PostMapping(value "/xcxPay")ResponseBodypublic Map<String,Object> miniAppPay(RequestBody byte[] req) {HashMap<String, Object> objectObjectMap new HashMap<>();…

【软件测试】--功能测试1

一、测试介绍 什么是软件&#xff1f; 控制计算机硬件工作的工具。 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 软件测试的目的&#xff1f; 减少软件缺陷&#xff0c;保证软件质量。 测试主流技能 1、功能测试 2、自动化测试 3、接口测试 4、性能测试 ​…

MySQL-事务,properties文件解析,连接池

1.事务机制管理 1.1 Transaction事务机制管理 默认情况下是执行一条sql语句就保存一次&#xff0c;那么比如我们需要三条数据同时成功或同时失败就需要开启事务机制了。开启事务机制后执行过程中发生问题就会回滚到操作之前&#xff0c;相当于没有执行操作。 1.2 事务的特征 事…

【初始RabbitMQ】延迟队列的实现

延迟队列概念 延迟队列中的元素是希望在指定时间到了之后或之前取出和处理消息&#xff0c;并且队列内部是有序的。简单来说&#xff0c;延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列使用场景 延迟队列经常使用的场景有以下几点&#xff1a; 订单在十分…

Anaconda下安装torch-geometric

主要流程参考&#xff1a;https://blog.csdn.net/weixin_45671036/article/details/130617637 https://blog.csdn.net/weixin_43756314/article/details/130225038?ops_request_misc&request_id&biz_id102&utm_term%E5%80%9F%E5%8A%A9anaconda%20%E5%AE%89%E8%A3%…