工厂设计模式总结

news/发布时间2024/5/14 22:43:35

一、简单工厂

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.bcls.cn/HWvL/3428.shtml

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

相关文章

操作系统--多线程的互斥、同步

一、概念 在进程/线程并发执行的过程中,进程/线程之间存在协作的关系,例如有互斥、同步的关系。 1.互斥 由于多线程执行操作共享变量的这段代码可能会导致竞争状态,因此我们将此段代码称为临界区(critical section)…

Linux(ACT)权限管理

文章目录 一、 ATC简介二、 案例1. 添加测试目录、用户、组,并将用户添加到组2. 修改目录的所有者和所属组3. 设定权限4. 为临时用户分配权限5. 验证acl权限 6. 控制组的acl权限 一、 ATC简介 ACL(Access Control List,访问控制列表&#xf…

element ui 安装 简易过程 已解决

我之所以将Element归类为Vue.js,其主要原因是Element是(饿了么团队)基于MVVM框架Vue开源出来的一套前端ui组件。我最爱的就是它的布局容器!!! 下面进入正题: 1、Element的安装 首先你需要创建…

使用LinkedList实现堆栈及Set集合特点、遍历方式、常见实现类

目录 一、使用LinkedList实现堆栈 堆栈 LinkedList实现堆栈 二、集合框架 三、Set集合 1.特点 2.遍历方式 3.常见实现类 HashSet LinkedHashSet TreeSet 一、使用LinkedList实现堆栈 堆栈 堆栈(stack)是一种常见的数据结构,一端…

抖音爬虫批量视频提取功能介绍|抖音评论提取工具

抖音爬虫是指通过编程技术从抖音平台上获取视频数据的程序。在进行抖音爬虫时,需要注意遵守相关法律法规和平台规定,以确保数据的合法获取和使用。 一般来说,抖音爬虫可以实现以下功能之一:批量视频提取。这个功能可以用于自动化地…

Android 解决后台服务麦克风无法录音问题

Android 解决后台无法录音问题 问题分析问题来源解决方案1. 修改清单文件:`AndroidManifest.xml`2. 修改启动服务方式3. 服务启动时创建前台通知并且指定前台服务类型参考文档最后我还有一句话要说我用心为你考虑黄浦江的事情,你心里想的却只有苏州河的勾当 问题分析 安卓9.…

WebRTC最新版报错解决:FileNotFoundError: LASTCHANGE.committime (二十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

SpringCloud-Gateway解决跨域问题

Spring Cloud Gateway是一个基于Spring Framework的微服务网关,用于构建可扩展的分布式系统。在处理跨域问题时,可以通过配置网关来实现跨域资源共享(CORS)。要解决跨域问题,首先需要在网关的配置文件中添加相关的跨域…

智慧建工的魔法:数据可视化的引领之光

在智慧建工的时代,数据可视化成为推动建筑行业进步的强大引擎,其作用不可忽视。通过将复杂的建筑数据以直观、清晰的图形展示出来,数据可视化为建筑工程提供了前所未有的便利和创新。 首先,数据可视化在建筑规划和设计阶段发挥关键…

Windows安装ElasticSearch

安装ES 官方网站:https://www.elastic.co/cn/elasticsearch 声明:JDK1.8 ,最低要求! Java开发,ElasticSearch的版本和我们之后的java核心包对应 windows安装 目录结构 目录熟悉 bin 启动文件 config 配置文件log4j…

数据结构-Queue队列

一,队列的简单认识 队列也是一种线性数据结构,与栈不同的是,它只能从一端添加元素,从另一端取出元素.定义了一端,另一端也就确定了. (当然还有一个特殊的双向队列LinkedList除外,它既可以从队首添加元素,也可以移除元素,队尾也是一样的,既可以添加元素,也可以移除元素) 二,队…

算法打卡day1|数组篇|Leetcode 704.二分查找、27.移除元素

数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合,可以方便的通过下标索引的方式获取到下标下对应的数据。 1.数组下标都是从0开始的。 2.数组内存空间的地址是连续的。 正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添…

如何连接ACL认证的Redis

点击上方蓝字关注我 应用程序连接开启了ACL认证的Redis时与原先的方式有差别,本文介绍几种连接开启ACL认证的Redis的Redis的方法。 对于RedisACL认证相关内容,可以参考历史文章: Redis权限管理体系(一):客户端名及用户…

TiDB离线部署、Tiup部署TiDB

先做tidb准备工作: 部署 TiDB 前的环境检查操作:TiDB 环境与系统配置检查 | PingCAP 文档中心 1.查看数据盘 fdisk -l (2,3)本人的分区已经是 ext4 文件系统不用分区,具体官方文档的分区: 4.查看数据盘…

小程序画布(二维地图线)

首先开始是想用小程序兼容openlayers的&#xff0c;但是了解到用不了&#xff0c;那就用画布来解决 实际效果如下 wxml中代码 <canvas id"trackDesignCanvas" //指定 id 的 Canvas 组件class"orbit-canvas-main" type"2d" …

鸿蒙DevEco Service开发准备与使用

DevEco低代码是一个基于Serverless和ArkUI的端云一体化低代码开发平台&#xff0c;可通过拖拽式开发&#xff0c;可视化配置构建元服务。打通HarmonyOS云侧与端侧能力&#xff0c;轻松实现HMS Core和AGC Serverless能力的调用。通过与元服务生态、HMS Core、AGC Serverless平台…

如何用GPT高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作?

原文链接&#xff1a;如何用GPT高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作?https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247594986&idx4&sn970f9ba75998f2dd9fa5707d1611a6cc&chksmfa82320dcdf5bb1bdf58c20686d4eb209770e68253ed90d…

opengl 学习纹理

一.纹理是什么&#xff1f; 纹理是一个2D图片&#xff08;甚至也有1D和3D的纹理&#xff09;&#xff0c;它可以用来添加物体的细节&#xff1b;类似于图像一样&#xff0c;纹理也可以被用来储存大量的数据&#xff0c;这些数据可以发送到着色器上。 采样是指用纹理坐标来获取纹…

【数据结构】链式队列

链式队列实现&#xff1a; 1.创建一个空队列 2.尾插法入队 3.头删法出队 4.遍历队列 一、main函数 #include <stdio.h> #include "./3.linkqueue.h" int main(int…

7.(数据结构)堆

7.1 相关概念 堆&#xff08;Heap&#xff09;在计算机科学中是一种特殊的数据结构&#xff0c;它通常被实现为一个可以看作完全二叉树的数组对象。以下是一些关于堆的基本概念&#xff1a; 数据结构&#xff1a; 堆是一个优先队列的抽象数据类型实现&#xff0c;通过完全二叉树…
推荐文章