当前位置: 首页 > news >正文

设计模式:简单工厂模式

工厂设计模式属于创建型模式,它提供了一种创建对象的最佳方式。工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。工厂模式属于创建型模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离。

面相对象编程中,万物皆对象。每个对象如果都通过关键字new创建,则会导致对象与其调用者耦合严重。假如更换要new的对象,则所有new对象的地方都需要改变代码,这显然违背了“开-闭原则”。如果使用工厂来生产对象,我们只需要和工厂打交道,彻底和对象解耦,如果更换对象,只需要在工厂里更换对象,而不需要再所有的地方进行更换,这样达到了与对象解耦的目的。工厂模式最大优点就是解耦

简单工厂模式

 简单工厂模式根据传入的参数,决定创建哪个类型的实例。简单工厂模式本着高内聚低耦合的原则,将系统的逻辑部分和功能分开。

使用场景 

首先当然是在你需要new一个类的对象的时候,此时各种状况出现啦:

  1. 你不想直接new这个类的对象,怕以后这个类改变的时候你需要回来改代码,而此时依赖这个类的地方已经到处都是了。
  2. 这个类的对象构建过程非常复杂,你不愿意将这么复杂的构建过程一遍又一遍的写在需要用到此对象的地方。
  3. 这个类的对象在构建过程中依赖了很多其他的类,而你无法在调用的地方提供
  • JDK源码中的 Calendar.getInstance()方法。
  • Logback源码中多个重载的 getLogger()方法。
  • QQ 换皮肤,一整套一起换。

  • 生成不同操作系统的程序。

简单工厂模式的3个角色: 

  • 对象工厂(SimpleFactory),负责实现创建所有产品实例的内部逻辑。
  • 抽象产品,即要生产的对象的接口,描述所有实例要实现的公共接口。
  • 具体产品,即创建的产品实例。所有创建的实例都是抽象产品的具体实现。

结构图:

优缺点

优点:

  • 结构简单,调用方便。工厂和产品的职责区分明确。
  • 客户端无需知道所创建具体产品的类名,只需知道参数即可。

缺点:

  • 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。
  • 违背“开放-关闭原则”,一旦添加新产品就必须修改简单工厂类的内部逻辑,工厂类代码会非常臃肿,违背高聚合原则。
  • 简单工厂模式使用了静态工厂方法,静态方法不能被继承和重写,造成工厂角色无法形成基于继承的等级结构。

应用实例: 

简易计算器为例,需求:输入两个数和运算符,得到结果。

抽象产品:

public abstract class Operation {protected abstract double compute (double number1, double number2) throws Exception;
}

具体产品:

// 加法
public class OperationAdd extends Operation{@Overrideprotected double compute(double number1, double number2) {return number1 + number2;}
}// 减法
public class OperationSub extends Operation{@Overrideprotected double compute(double number1, double number2) {return number1 - number2;}
}// 乘法
public class OperationMul extends Operation{@Overrideprotected double compute(double number1, double number2) {return number1 * number2;}
}// 除法
public class OperationDiv extends Operation{@Overrideprotected double compute(double number1, double number2) throws Exception {if(number2 == 0){throw new Exception("除数不能为0!");}return number1 / number2;}
}

对象工厂:

这里对简单工厂创建产品进行了优化,可以通过缓存、配置文件、反射和泛型等技术了优化。

如果运算业务需要扩展,需要创建具体运算类即可,不需要再修改简单工厂类了。

public class OperationFactory {private static final Map<String, Operation> cachedParsers = new HashMap<>();static {cachedParsers.put("+", new OperationAdd());cachedParsers.put("-", new OperationSub());cachedParsers.put("*", new OperationMul());cachedParsers.put("/", new OperationDiv());}public static Operation createOperate0(String operate) {if (operate == null || operate.isEmpty()) {return null;//返回null还是IllegalArgumentException全凭你自己说了算}return cachedParsers.get(operate);}/***  createOperate0运用缓存技术,节省内存和对象创建的时间*  createOperate0 和 createOperate1 同理*/public static Operation createOperate1(String operate){Operation operation = null;switch (operate){case "+":operation = new OperationAdd(); break;case "-":operation = new OperationSub(); break;case "*":operation = new OperationMul(); break;case "/":operation = new OperationDiv(); break;}return operation;}/*** createOperate1方法不符合开闭原则*      如果运算业务继续扩展,需要创建具体运算类,也需要修改简单工厂的 createOperate1方法。* 采用反射技术进行优化,即createOperate2方法*/public static Operation createOperate2(String className){Operation operation = null;try {if(!(null == className || "".equals(className))){operation = (Operation) Class.forName(className).newInstance();}} catch (Exception e) {e.printStackTrace();}return operation;}/*** createOperate2方法中类型强制转型,参数为字符串,可控性不高* 采用反射和泛型技术进行优化,即createOperate3方法*/public static Operation createOperate3(Class<? extends Operation> clazz){try {if(null != clazz){return clazz.newInstance();}} catch (Exception e) {e.printStackTrace();}return null;}}

测试:

public class Test {public static void main(String[] args) throws Exception {double num1 = 10;double num2 = 2;System.out.println(OperationFactory.createOperate0("*").compute(num1, num2));System.out.println(OperationFactory.createOperate1("*").compute(num1, num2));Operation operate2 = OperationFactory.createOperate2("cn.jq.learn.simplefactorypattern.OperationDiv");System.out.println(operate2.compute(num1, num2));Operation operate3 = OperationFactory.createOperate3(OperationAdd.class);System.out.println(operate3.compute(num1, num2));}
}

相关文章:

设计模式:简单工厂模式

工厂设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。工厂模式属于创建型模式&#xff0c;它在创建对象时提供了一种封装机制&#xff0c;将实际创建对象的代码与使用代码分离。 …...

老龄化对投资意味着什么?

1月15日&#xff0c;国务院办公厅印发《关于发展银发经济增进老年人福祉的意见》从4个方面提出26项举措&#xff0c;为我国首个以“银发经济”命名的政策文件。 近期&#xff0c;国信证券分析师王开发布题为《银发经济再思考&#xff1a;老龄化对投资的影响》的报告&#xff0…...

从公有云对象存储迁移到回私有化 MinIO需要了解的所有信息

我们上一篇文章《如何从 AWS S3 遣返到 MinIO》的反响非常出色 - 我们已经接到了数十个企业的电话&#xff0c;要求我们提供遣返建议。我们已将这些回复汇总到这篇新文章中&#xff0c;其中我们更深入地研究了与遣返相关的成本和节省&#xff0c;以便您更轻松地进行自己的分析。…...

C#颜色拾取器

1&#xff0c;目的&#xff1a; 获取屏幕上任意位置像素的色值。 2&#xff0c;知识点: 热键的注册与注销。 /// <summary>/// 热键注册/// </summary>/// <param name"hWnd">要定义热键的窗口的句柄 </param>/// <param name"id…...

最长公共子串的问题(正常方法和矩阵法,动态规划)

题目&#xff1a; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符…...

Linux实验记录:使用LVM(逻辑卷管理器)

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 备注&#xff1a; 硬盘分好区或者部署为RAID磁盘阵列…...

[设计模式Java实现附plantuml源码~创建型] 复杂对象的组装与创建——建造者模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…...

【国产MCU】-认识CH32V307及开发环境搭建

认识CH32V307及开发环境搭建 文章目录 认识CH32V307及开发环境搭建1、CH32V307介绍2、开发环境搭建3、程序固件下载1、CH32V307介绍 CH32V307是沁恒推出的一款基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度…...

python flask request教程

request 一、传json1、resquest.get_data()与resquest.data2、request.get_json()3、request.json["imageURL"]二、传file1、request.files["file"]2、request.form["username"]3、request.form.get(username)与2等价,其他get()与[]也相同三、其…...

UE5 Chaos系统 学习笔记

记得开插件&#xff1a; 1、锚点场&#xff08;构造场&#xff09; 在锚点场范围内的物体静止且不被其他力场损坏 需要在Geometry Collection的初始化场把构造场设置过去 2、ClusterStrain 破裂效果的力 3、DisableField chaos破裂后的模拟物理在绿色范围内禁止行为和模拟物…...

MkDocs 部署指南

简介 MkDocs 可以同时编译多个 markdown 文件&#xff0c;形成书籍一样的文件。有多种主题供你选择&#xff0c;很适合项目使用。 MkDocs 是快速&#xff0c;简单和华丽的静态网站生成器&#xff0c;可以构建项目文档。文档源文件在 Markdown 编写&#xff0c;使用单个 YAML …...

【Java 设计模式】行为型之访问者模式

文章目录 1. 定义2. 应用场景3. 代码实现结语 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;用于在不改变被访问元素的类的前提下定义对这些元素的新操作。访问者模式将数据结构与作用于结构上的操作解耦&#xff0c;使得操作集合可以灵…...

堆和堆排序【数据结构】

目录 一、堆1. 堆的存储定义2. 初始化堆3. 销毁堆4. 堆的插入向上调整算法 5. 堆的删除向下调整算法 6. 获取堆顶数据7. 获取堆的数据个数8. 堆的判空 二、Gif演示三、 堆排序1. 堆排序(1) 建大堆(2) 排序 2.Topk问题 四、完整代码1.堆的代码Heap.cHeap.htest.c 2. 堆排序的代码…...

【全程录屏GPT3.5升级4.0】2024最新GPT4升级订阅详细指南

前言&#xff1a;为什么要升级GPT4.0&#xff0c;下图是来自GPT4.0的官方回答&#xff0c;可以看出&#xff0c;GPT4无愧于是一个大版本升级的。 一、视频教程 记录了普通用户使用WildCrad从GPT3.5升级到4.0的全部过程&#xff0c;感兴趣可以前往观看&#xff1a;https://www.…...

中移(苏州)软件技术有限公司面试问题与解答(4)—— virtio所创建的设备1

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;0&#xff09;—— 面试感悟与问题记录 本文参考以下文章&#xff1a; VirtIO实现原理——PCI基础 VirtIO实现原理——virtblk设备初始化 特此致谢&#xff01; 本文对…...

《动手学深度学习(PyTorch版)》笔记5

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过,…...

QT中wchar_t类型如何输出

在Qt中&#xff0c;通常使用QString来处理字符串&#xff0c;而不是wchar_t。QString是Qt中用于处理Unicode字符串的类。如果你有wchar_t类型的字符串&#xff0c;你可以将其转换为QString进行输出。 以下是一个简单的例子&#xff1a; #include <QCoreApplication> #i…...

网络安全04-sql注入靶场第一关

目录 一、环境准备 1.1我们进入第一关也如图&#xff1a; ​编辑 二、正式开始第一关讲述 2.1很明显它让我们在标签上输入一个ID&#xff0c;那我们就输入在链接后面加?id1 ​编辑 2.2链接后面加个单引号()查看返回的内容&#xff0c;127.0.0.1/sqli/less-1/?id1,id1 …...

微服务理解篇

一 :架构演变 1 单体架构: 简单理解为一个服务涵盖所有需求功能2 垂直架构: 按照业务功能将单体架构拆分成小模块服务, 如:订单系统,用户系统,商品系统 ##缺点 引入分布式事务,分布式锁等,优点:模块解耦## 垂直拆分:根据业务层级拆分,比如商城的订单系统,用户系统,商品系统…...

项目篇:基于TCP通信模型的外卖软件实现

一、基本成员及功能实现 本项目主要由服务器&#xff0c;消费者&#xff0c;商家&#xff0c;外卖员组成。基本的功能如下。 对所有人&#xff1a; 1、可以注册登录 2、可以修改个人信息 3、可以销户 商家&#xff1a; 1、注册时需要填写售卖商品信息 2、可以修改商品信…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...