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

简单工厂VS工厂方法

工厂方法模式–制造细节无需知

前面介绍过简单工厂模式,简单工厂模式只是最基本的创建实例相关的设计模式。在真实情况下,有更多复杂的情况需要处理。简单工厂生成实例的类,知道了太多的细节,这就导致这个类很容易出现难维护、灵活性差的问题。就像我们去饭店吃饭,只需要付钱,等成品,不需要了解这盘菜是怎么做的,如何加工的。

简单工厂

再来回顾下简单工厂模式的计算器功能的工厂类。

在这里插入图片描述

public static Operation createOperate(String operate) {Operation oper = null;switch (operate) {case "+":oper = new Add();break;case "-":oper = new Sub();break;case "*":oper = new Mul();break;case "/":oper = new Div();break;}return oper;
}

客户端调用时

Operation operate = OperationFactory.createOperate(strOperate);
double result = operate.getResult(numberA, numberB);

当使用工厂方法模式实现

实际就是对简单工厂中的细节部分进行再封装,让这个工厂类不需要知道很多的实现细节。是这样子吗,体验一下子。

结构图如下:

在这里插入图片描述

先构建一个工厂接口

public interface IFactory {Operation createOperation();
}

然后加减乘除的工厂都去实现这个接口,并实现自己的createOeration()方法

// 加法工厂
public class AddFactory implements IFactory {@Overridepublic Operation createOperation() {return new Add();}
}// 减法工厂
public class SubFactory implements IFactory {@Overridepublic Operation createOperation() {return new Sub();}
}// 乘法工厂
public class MulFactory implements IFactory {@Overridepublic Operation createOperation() {return new Mul();}
}// 除法工厂
public class DivFactory implements IFactory {@Overridepublic Operation createOperation() {return new Div();}
}

那么在对外工厂类中就可以这么实现

public class OperationFactory {public static Operation createOperate(String operate) {Operation oper = null;IFactory factory = null;switch (operate) {case "+":factory = new AddFactory();break;case "-":factory = new SubFactory();break;case "*":factory = new MulFactory();break;case "/":factory = new DivFactory();break;}oper = factory.createOperation();return oper;}}

当我需要增加新的运算功能时,需要增加运算类,运算工厂类,一下增加了好几个类,这样是不是变得更麻烦了?

简单工厂VS工厂方法

简单工厂模式的最大优点在于工厂类中包含必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

就像计算器工厂类,客户端只需要传入一个"+"或别的,就能得到想要的功能算法。

但是当我们继续增加计算器功能时,比如增加一个指数运算,增加一个对数运算,要去不断修改OperationFactory类,就违背了开放-封闭原则。那我们该如何降低这种风险呢?就需要使用到工厂方法模式

我们应该尽量将长的代码分派切割成小段,再将每一小段封装起来,减少每段代码之间的耦合,这样风险就分散了,需要修改或扩展的难度就降低了。

再以计算器功能为例,项目起初,我们只知道加减乘除的功能,那我们就可以将这四个功能定义为基础运算工厂,也就是说前期功能是确定的,作为基础功能,我们就没有必要给加减乘除类增加冗余的工厂了。

后来增加了指数、对数运算,我们定义为高级运算工厂

那么其实并不是如上面的代码所讲,加减乘除功能每一个功能需要一个工厂类。而是将加减乘除用一个基础工厂来创建,而后面增加新的产品功能,又不想影响原有的工厂代码,于是就扩展一个新的工厂来处理即可。

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到子类

修改结构图:

在这里插入图片描述

新增两个运算类(指数和对数)

// 指数
public class Pow extends Operation {@Overridepublic double getResult(double numberA, double numberB) {return Math.pow(numberA, numberB);}
}// 对数运算
public class Log extends Operation {@Overridepublic double getResult(double numberA, double numberB) {return Math.log(numberB) / Math.log(numberA);}
}

工厂接口不变

public interface IFactory {Operation createOperation(String operType);
}

基础运算工厂类,此类已经比较成熟稳定,实现后应该封装到位,不建议轻易修改此类

public class FactoryBase implements IFactory {@Overridepublic Operation createOperation(String operate) {Operation oper = null;switch (operate) {case "+":oper = new Add();break;case "-":oper = new Sub();break;case "*":oper = new Mul();break;case "/":oper = new Div();break;}return oper;}
}

高级运算工厂类,也许还有扩展产品的可能性

public class FactoryAdvanced implements IFactory {@Overridepublic Operation createOperation(String operType) {Operation oper = null;switch (operType) {case "pow":oper = new Pow();break;case "log":oper = new Log();break;}return oper;}
}

那么最后一步就是对外工厂类,根据传入的参数,选择具体使用哪个工厂类。

public class OperationFactory {public static Operation createOperate(String operate) {Operation oper = null;IFactory factory = null;switch (operate) {case "+":case "-":case "*":case "/":factory = new FactoryBase();break;case "pow":case "log":factory = new FactoryAdvanced();}oper = factory.createOperation(operate);return oper;}}

总结

工厂方法模式是简单工厂模式的进一步抽象和推广。工厂方法模式本质就是对获取对象过程的抽象。

对于复杂的参数的构造对象,可以很好地对外层屏蔽代码的复杂性,有很好的解耦能力。

相关文章:

简单工厂VS工厂方法

工厂方法模式–制造细节无需知 前面介绍过简单工厂模式,简单工厂模式只是最基本的创建实例相关的设计模式。在真实情况下,有更多复杂的情况需要处理。简单工厂生成实例的类,知道了太多的细节,这就导致这个类很容易出现难维护、灵…...

使用VSCODE链接Anaconda

打代码还是在VSCODE里得劲 所以得想个办法在VSCODE里运行py文件 一开始在插件商店寻找插件 但是没有发现什么有效果的 幸运的是VSCODE支持自己选择Python的编译器 打开VSCODE 按住CtrlShiftP 输入Select Interpreter 如果电脑已经安装上了Python的环境 VSCODE会默认选择普通…...

Mysql数据库 9.SQL语言 查询语句 连接查询、子查询

连接查询 通过查询多张表,用连接查询进行多表联合查询 关键字:inner join 内连接 left join 左连接 right join 右连接 数据准备 创建新的数据库:create database 数据库名; create database db_test2; 使用数据库:use 数据…...

二叉树按二叉链表形式存储,试编写一个判别给定二叉树是否是完全二叉树的算法

完全二叉树:就是每层横着划过去是连起来的,中间不会断开 比如下面的左图就是完全二叉树 再比如下面的右图就是非完全二叉树 那我们可以采用层序遍历的方法,借助一个辅助队列 当辅助队列不空的时候,出队头元素,入队头…...

Android自定义控件

目录 Android自定义控件一、对现有控件进行扩展二、创建复合控件1 定义属性2 组合控件3 引用UI模板 三、重写View来实现全新控件1 弧线展示图1.1 具体步骤: 2 音频条形图2.1 具体步骤 四、补充:自定义ViewGroup Android自定义控件 ref: Android自定义控件…...

Java 中的 Cloneable 接口和深拷贝

引言: 在 Java 中,深拷贝是一种常见的需求,它可以创建一个对象的完全独立副本。Cloneable 接口提供了一种标记机制,用于指示一个类实例可以被复制。本文将详细介绍 Java 中的 Cloneable 接口和深拷贝的相关知识&#xff0…...

项目实战:通过axios加载水果库存系统的首页数据

1、创建静态页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"style/index.css"><script src"script/axios.mi…...

RK3568平台 内存的基本概念

一.Linux的Page Cache page cache&#xff0c;又称pcache&#xff0c;其中文名称为页高速缓冲存储器&#xff0c;简称页高缓。page cache的大小为一页&#xff0c;通常为4K。在linux读写文件时&#xff0c;它用于缓存文件的逻辑内容&#xff0c;从而加快对磁盘上映像和数据的访…...

mysql联合索引和最左匹配问题。

1引言&#xff1a; 如果频繁地使⽤相同的⼏个字段查询&#xff0c;就可以考虑建⽴这⼏个字段的联合索引来提⾼查询效率。⽐如对 于联合索引 test_col1_col2_col3&#xff0c;实际建⽴了 (col1)、(col1, col2)、(col, col2, col3) 三个索引。联合 索引的主要优势是减少结果集数量…...

全球发布|首个AI视角下的生态系统架构解读—《生态系统架构--人工智能时代从业者的新思维》重磅亮相!

点击可免费注册下载 &#x1f447; 人工智能时代的企业架构师必读系列 《生态系统架构--人工智能时代从业者的新思维》 Philip Tetlow、Neal Fishman、Paul Homan、Rahul著 The Open Group Press 2023年11月出版 这本书可以很好地帮助全球架构师使用人工智能来构建、开发和…...

解决torch.hub.load加载网络模型异常

1 torch.hub.load 加载网络模型错误 通过网络使用torch.hub.load加载模型代码如下&#xff1a; self.model torch.hub.load("facebookresearch/dinov2", dinov2_vits14, sourcegithub).to(self.device) 运行网上的项目&#xff0c;经常会卡住或者超时&#xff0c…...

如何获取HuggingFace的Access Token;如何获取HuggingFace的API Key

Access Token通过编程方式向 HuggingFace 验证您的身份&#xff0c;允许应用程序执行由授予的权限范围&#xff08;读取、写入或管理&#xff09;指定的特定操作。您可以通过以下步骤获取&#xff1a; 1.首先&#xff0c;你需要注册一个 Hugging Face 账号。如果你已经有了账号…...

How to resolve jre-openjdk and jre-openjdk-headless conflicts?

2023-11-05 Archlinux 执行 pacman -Syu 显示 failed to prepare transaction&#xff1b;jre-openjdk and jre-openjdk-headless conflicts 解决 archlinux sudo pacman -Sy jdk-openjdk...

setTimeout和setImmediate以及process.nextTick的区别?

目录 前言 setTimeout 特性和用法 setImmediate 特性和用法 process.nextTick 特性和用法 区别和示例 总结 在Node.js中&#xff0c;setTimeout、setImmediate和process.nextTick是用于调度异步操作的三种不同机制。它们之间的区别在于事件循环中的执行顺序和优先级。…...

read 方法为什么返回 int 类型

在Java的输入流&#xff08;InputStream&#xff09;中&#xff0c;read方法返回int类型的值的原因是为了提供更多的信息和灵活性。虽然这可能看起来有些不直观&#xff0c;但有一些合理的考虑和用途&#xff0c;主要包括以下几点&#xff1a; EOF标志&#xff1a;read方法返回…...

在二维矩阵/数组中查找元素 Leetcode74, Leetcode240

这一类题型中二维数组的元素取值有序变化&#xff0c;因此可以用二分查找法。我们一起来看一下。 一、Leetcode 74 Leetcode 74. 搜索二维矩阵 这道题要在一个二维矩阵中查找元素。该二维矩阵有如下特点&#xff1a; 每行元素 从左到右 按非递减顺序排列。每行的第一个元素 …...

MS35657步进电机驱动器可兼容DRV8824

MS35657 是一款双通道 DMOS 全桥驱动器&#xff0c;可以驱动一个步进电机或者两个直流电机。可兼容DRV8824&#xff08;功能基本一致&#xff0c;管脚不兼容&#xff09;。每个全桥的驱动电流在 24V 电源下可以工作到 1.4A。MS35657 集成了固定关断时间的 PWM 电流校正器&#…...

SQL语句性能优化

1、查询 SQL 尽量不要使用 select *,而是 select 具体字段 反例子: select * from sys_user; 正例子: select id,name from sys_user; 理由如下: 只取需要的字段,节省资源、减少网络开销。select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。…...

线性代数之 伪逆矩阵

目录 一、伪逆矩阵 ◼ A的伪逆矩阵与SVD ◼ 用Python代码计算A的伪逆矩阵 ◼ 笔算A的伪逆矩阵 一、伪逆矩阵 ◼ A的伪逆矩阵与SVD 逆矩阵并不总是存在&#xff0c;即使是方阵。然而&#xff0c;对于非正方形矩阵&#xff0c;存在一个伪逆矩阵&#xff0c;也叫摩尔-彭罗斯…...

【3D图像分割】基于Pytorch的VNet 3D 图像分割5(改写数据流篇)

在这篇文章&#xff1a;【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割2&#xff08;基础数据流篇&#xff09; 的最后&#xff0c;我们提到了&#xff1a; 在采用vent模型进行3d数据的分割训练任务中&#xff0c;输入大小是16*96*96&#xff0c;这个的裁剪是放到Dataset类…...

三角函数公式速查手册:从基础到进阶的实用指南

三角函数公式速查手册&#xff1a;从基础到进阶的实用指南 三角函数是数学中最基础也最重要的工具之一&#xff0c;无论是学生应对考试&#xff0c;还是开发者在图形编程、信号处理等领域的实际应用&#xff0c;都离不开这些公式的灵活运用。本文将系统整理从基础定义到高级变换…...

OpenCV实战:图像亮度、对比度与锐化的智能调节与优化

1. 图像处理基础概念解析 在开始动手实践之前&#xff0c;我们需要先理解几个关键概念。亮度、对比度和锐化这三个参数就像调节电视画面的三个旋钮&#xff0c;每个旋钮都会对图像产生独特的影响。 亮度&#xff08;Brightness&#xff09;就像房间里的灯光开关。调高亮度&…...

从‘梯度裁剪’到‘权重初始化’:一份预防梯度爆炸的PyTorch/TensorFlow实操清单

从‘梯度裁剪’到‘权重初始化’&#xff1a;一份预防梯度爆炸的PyTorch/TensorFlow实操清单 训练深度神经网络时&#xff0c;梯度爆炸问题就像一颗定时炸弹——它可能在你最意想不到的时候突然引爆&#xff0c;导致损失函数值瞬间变为NaN&#xff0c;或者权重更新出现剧烈震荡…...

Phi-3-mini-4k-instruct-gguf效果展示:q4量化下保持语义准确性的中文生成实录

Phi-3-mini-4k-instruct-gguf效果展示&#xff1a;q4量化下保持语义准确性的中文生成实录 1. 轻量级文本生成新选择 Phi-3-mini-4k-instruct-gguf是微软Phi-3系列中的轻量级文本生成模型GGUF版本&#xff0c;专为问答、文本改写、摘要整理和简短创作等场景优化。这个经过q4量…...

游戏多开检测技术深度解析与实战绕过方案

1. 游戏多开检测技术全景解析 游戏多开检测本质上是一种防止同一程序重复运行的技术手段。我在逆向分析各类游戏客户端时发现&#xff0c;现代游戏通常会采用组合拳式的检测策略&#xff0c;从简单的进程查找到复杂的驱动级验证&#xff0c;防御层级越来越深。对于开发者而言&a…...

别等电脑挂了后悔,教你现在就查看Bitlocker密钥

网管小贾 / sysadm.cc陈主任晃了晃脑袋&#xff0c;皱着眉冲着刘晓白说道&#xff1a;“简历我看过了&#xff0c;就算请我吃饭&#xff0c;恐怕也很难办啊&#xff01;” 刘晓白则一呲牙&#xff1a;“我说老舅&#xff0c;要进你们公司&#xff0c;还不是您一句话的事儿嘛&am…...

MelonLoader终极指南:Unity游戏模组加载器的完整安装与使用教程

MelonLoader终极指南&#xff1a;Unity游戏模组加载器的完整安装与使用教程 【免费下载链接】MelonLoader The Worlds First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono 项目地址: https://gitcode.com/gh_mirrors/me/MelonLoader 还在…...

GTX1650也能跑!Windows11上OLLAMA+AnythingLLM本地部署Llama3保姆级教程

GTX1650也能跑&#xff01;Windows11上OLLAMAAnythingLLM本地部署Llama3保姆级教程 老旧硬件也能玩转大模型&#xff1f;当GTX1650这样的入门级显卡遇上Llama3这类前沿AI模型&#xff0c;很多人第一反应可能是"跑不动"。但经过实测&#xff0c;只要合理配置和优化&am…...

HARMONYOS应用实例258:反比例函数图像

反比例函数图像 功能:绘制双曲线,点击图像上的点显示坐标,验证 xy=kxy=kxy=k 的恒等关系。 应用功能: 绘制反比例函数双曲线图像 y = k/x 可调节k值,范围从1到20...

Qwen2.5-14B-Instruct+Pixel Script Temple:高校戏剧系AI辅助教学实战案例

Qwen2.5-14B-InstructPixel Script Temple&#xff1a;高校戏剧系AI辅助教学实战案例 1. 项目背景与价值 在高校戏剧教育领域&#xff0c;剧本创作一直是教学难点。传统教学模式下&#xff0c;学生需要花费大量时间在格式规范、基础场景构建等基础性工作上&#xff0c;而教师…...