设计模式从入门到精通之(一)工厂模式

工厂模式:为每个工厂找到"生意经"

在现实生活中,我们随处可见"工厂"的影子,比如汽车工厂生产汽车,食品工厂生产食品。但你有没有想过,为什么我们需要工厂?如果没有工厂,我们自己能不能搞定这些生产?今天,我们就用现实中的例子来引入软件设计中的工厂模式

1. 什么是工厂模式?

工厂模式(Factory Pattern)是一种创建型设计模式,它通过为对象的创建提供一种统一的接口,来隐藏实例化的具体逻辑。简单来说,工厂模式就像一台机器,它为你定制化地生产出想要的东西,而不需要你自己动手去捣鼓具体的制作过程。

在代码世界里,工厂模式能够帮助我们解决"简单对象创建"变成"复杂耦合代码"的问题,减少维护难度。

2. 用现实中的故事引出工厂模式

假设你是一名咖啡爱好者,每天早晨都需要喝一杯咖啡来提神。家里有各种原材料,比如咖啡豆、牛奶、糖等等。但是如果让你每天一大早起来,自己磨豆、煮咖啡、打奶泡,是不是感觉太麻烦?如果有一家咖啡店帮你制作出各种类型的咖啡,比如美式、拿铁、卡布奇诺,你只需要说出你想喝的咖啡名称就行,岂不是省时省力?

这家咖啡店就是一个工厂,它屏蔽了制作过程的复杂性,让你通过简单的请求(咖啡名称),得到想要的结果(咖啡)。

3. 工厂模式的代码实现

我们用代码来模拟这个场景,看看如何用工厂模式来制作咖啡。

3.1 咖啡类

每种咖啡都有自己的特点,我们用不同的类来表示。

// 定义咖啡的抽象类
abstract class Coffee {public abstract String getName();public void prepare() {System.out.println("Preparing ingredients for " + getName());}
}// 美式咖啡
class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "American Coffee";}
}// 拿铁咖啡
class LatteCoffee extends Coffee {@Overridepublic String getName() {return "Latte Coffee";}
}

3.2 咖啡工厂

为了屏蔽咖啡的具体制作细节,我们创建一个咖啡工厂。

class CoffeeFactory {public static Coffee createCoffee(String type) {if ("American".equalsIgnoreCase(type)) {return new AmericanCoffee();} else if ("Latte".equalsIgnoreCase(type)) {return new LatteCoffee();} else {throw new IllegalArgumentException("Unknown coffee type: " + type);}}
}

3.3 客户端代码

客户端只需要和工厂交互,就可以获取不同种类的咖啡,而不用关心咖啡是怎么制作的。

public class CoffeeShop {public static void main(String[] args) {Coffee american = CoffeeFactory.createCoffee("American");american.prepare();Coffee latte = CoffeeFactory.createCoffee("Latte");latte.prepare();}
}

运行结果:

Preparing ingredients for American Coffee
Preparing ingredients for Latte Coffee

4. 工厂模式的优缺点

优点:

    1. 解耦:客户端与具体产品类解耦,新增产品时只需要修改工厂类。
    1. 高内聚:对象创建的逻辑集中在工厂中,代码更清晰。

缺点:

    1. 工厂类的职责可能会变得过重,容易违背单一职责原则。
    1. 每增加一种新产品,都需要修改工厂类代码,违反开闭原则(这可以通过工厂方法模式改进)。

5. 总结

工厂模式是最常用的设计模式之一,它的核心思想就是将创建对象的逻辑集中管理,减少代码中的重复和耦合。通过咖啡店的例子,我们可以更容易理解工厂模式的用途。

在未来的专栏中,我们还会讲解其他设计模式,比如单例模式可以确保一杯咖啡只做一份,而装饰器模式可以为你的咖啡添加额外的配料。每一种设计模式,就像现实世界中的一套工具,帮助你更高效地构建程序。

思考问题:
如果你想扩展工厂模式,比如支持更多种类的咖啡(比如卡布奇诺),你会如何设计?欢迎在评论区分享你的看法!

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

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

相关文章

谈谈你对vue这种框架理解

发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。 Vue.js 是一个渐进式的前端 JavaScript 框架,旨在通过提供易于理解、上手简单且功能强大的工具来构建现代化的 Web …

使用html2canvas实现前端截图

一、主要功能 网页截图:html2canvas通过读取DOM结构和元素的CSS样式,在客户端生成图像,不依赖于服务端的渲染。它可以将指定的DOM元素渲染为画布(canvas),并生成图像。多种输出格式:生成的图像…

微信小程序横屏页面跳转后,自定义navbar样式跑了?

文章目录 问题原因:解决方案: 今天刚遇到的问题,横屏的页面完成操作后跳转页面后,自定义的tabbar样式乱了,跑到最顶了,真机调试后发现navbar跑到手机状态栏了,它正常应该跟右边胶囊一行。 知道问…

Vivado ILA数据导出MATLAB分析

目录 ILA数据导出 分析方式一 分析方式二 有时候在系统调试时,数据在VIVADO窗口获取的信息有限,可结合MATLAB对已捕获的数据进行分析处理 ILA数据导出 选择信号,单击右键后,会有export ILA DATA选项,将其保存成CS…

《探索形象克隆:科技与未来的奇妙融合》

目录 一、什么是形象克隆 二、形象克隆的技术原理 三、形象克隆的发展现状 四、形象克隆的未来趋势 五、形象克隆的应用场景 六、形象克隆简单代码案例 Python 实现数字人形象克隆 Scratch 实现角色克隆效果(以猫为例) JavaScript 实现 Scratc…

MATLAB深度学习(七)——ResNet残差网络

一、ResNet网络 ResNet是深度残差网络的简称。其核心思想就是在,每两个网络层之间加入一个残差连接,缓解深层网络中的梯度消失问题 二、残差结构 在多层神经网络模型里,设想一个包含诺干层自网络,子网络的函数用H(x)来表示&#x…

前端入门之VUE--vue组件化编程

前言 VUE是前端用的最多的框架;这篇文章是本人大一上学习前端的笔记;欢迎点赞 收藏 关注,本人将会持续更新。 文章目录 2、Vue组件化编程2.1、组件2.2、基本使用2.2.1、VueComponent 2、Vue组件化编程 2.1、组件 组件:用来实现…

设计模式-装饰器模式(结构型)与责任链模式(行为型)对比,以及链式设计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1.装饰器模式1.1概念1.2作用1.3应用场景1.4特点1.5类与对象关系1.6实现 2责任链模式2.1概念2.2作用2.3应用场景2.4特点2.5类与对象关系2.6实现 3.对比总结 前言…

交叉熵损失函数(Cross-Entropy Loss)

原理 交叉熵损失函数是深度学习中分类问题常用的损失函数,特别适用于多分类问题。它通过度量预测分布与真实分布之间的差异,来衡量模型输出的准确性。 交叉熵的数学公式 交叉熵的定义如下: C r o s s E n t r o y L o s s − ∑ i 1 N …

操作系统:死锁与饥饿

目录 死锁概念 饥饿与饿死概念 饥饿和死锁对比 死锁类型 死锁条件(Coffman条件) 死锁恢复方法 死锁避免 安全状态与安全进程序列: 银行家算法: 死锁检测时机(了解): 死锁检测 死锁案…

Prisoner’s Dilemma

囚徒困境博弈论解析 什么是囚徒困境? 囚徒困境(Prisoner’s Dilemma)是博弈论中的一个经典模型,用来分析两名玩家在非合作环境下的决策行为。 其核心在于玩家既可以选择合作也可以选择背叛,而最终的结果取决于双方的…

RPO: Read-only Prompt Optimization for Vision-Language Few-shot Learning

文章汇总 想解决的问题对CoOp的改进CoCoOp尽管提升了性能,但却增加了方差(模型的准确率波动性较大)。 模型的框架一眼看去,跟maple很像(maple跟这篇文章都是2023年发表的),但maple的视觉提示是由文本提示经过全连接转换而来的,而这里是文本提示和视觉提示是独立的。另外m…

『MySQL 实战 45 讲』24 - MySQL是怎么保证主备一致的?

MySQL是怎么保证主备一致的? MySQL 主备的基本原理 基本的主备切换流程 状态 1:客户端的读写都直接访问节点 A,而节点 B 是 A 的备库状态 2:切换时,读写访问的都是节点 B,而节点 A 是 B 的备库注意&…

自荐一部IT方案架构师回忆录

作者本人毕业于一个不知名大专院校,所读专业计算机科学技术。2009年开始IT职业生涯,至今工作15年。擅长TSQL/Shell/linux等技术,曾经就职于超万人大型集团、国内顶级云厂商、央国企公司。参与过运营商大数据平台、大型智慧城市ICT、云计算、人…

python数据分析之爬虫基础:selenium详细讲解

目录 1、selenium介绍 2、selenium的作用: 3、配置浏览器驱动环境及selenium安装 4、selenium基本语法 4.1、selenium元素的定位 4.2、selenium元素的信息 4.3、selenium元素的交互 5、Phantomjs介绍 6、chrome handless模式 1、selenium介绍 (1…

【数据结构——查找】顺序查找(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现顺序查找的算法。 相关知识 为了完成本关任务,你需要掌握:1.根据输入数据建立顺序表,2.顺序表的输出,…

光伏电站建设成本利润估算

​截至2024年9月底,全国光伏发电装机容量达到7.7亿千瓦,同比增长48.4%。其中集中式光伏4.3亿千瓦,分布式光伏3.4亿千瓦。2024年前三季度,全国光伏发电量6359亿千瓦时,同比增长45.5%。全国光伏发电利用率97.2%,同比下降1.1个百分点.早在今年2月份,中国光伏行业协会名誉理…

create-react-app react19 搭建项目报错

报错截图 此时运行会报错: 解决方法: 1.根据提示安装依赖法 执行npm i web-vitals然后重新允许 2.删除文件法 在index.js中删除对报错文件的引入,删除报错文件

scala的集合性能2

可变集合\n可变集合允许在原地修改数据,适合需要频繁更新的场景。Scala 的可变集合包括 ArrayBuffer、HashSet和HashMap。 1. ArrayBuffer\nArrayBuffer 是一个可变的动态数组,提供高效的随机访问和添加操作。 import scala.collection.mutable.ArrayB…

【Ubuntu】脚本自动化控制终端填充

1.sh脚本文件控制终端写入命令 在SLAM算法中,每次启动vins都需要起很多终端,尽管使用了超级终端Terminator可以终端内划分看起来更加便捷,但是每次起算法的命令还是要自己输入,已经被麻烦了两年了,今天突然想写写一个…