《工厂模式在软件开发中的深度剖析与应用》
工厂模式
在软件开发的领域中,设计模式充当着解决常见问题的高效且可复用的策略角色。其中,工厂模式作为创建对象的重要设计模式,具有不可小觑的应用价值。接下来,我们将深入探讨简单工厂模式、工厂方法模式和抽象工厂模式。
一、简单工厂模式
简单工厂模式虽未被纳入 23 种经典设计模式,但可视为工厂模式的一种简化且特殊的实现方式。
(一)基础版
// 咖啡产品的接口
public interface Coffee {void make();
}// 美式咖啡类,实现 Coffee 接口
public class Americano implements Coffee {@Overridepublic void make() {System.out.println("正在制作美式咖啡");}
}// 摩卡咖啡类,实现 Coffee 接口
public class Mocha implements Coffee {@Overridepublic void make() {System.out.println("正在制作摩卡咖啡");}
}// 卡布奇诺咖啡类,实现 Coffee 接口
public class Cappuccino implements Coffee {@Overridepublic void make() {System.out.println("正在制作卡布奇诺咖啡");}
}// 简单工厂类
public class CoffeeSimpleFactory {/*** 根据传入的字符串类型创建对应的咖啡对象* @param type 咖啡类型的字符串* @return 对应的咖啡对象,如果类型不匹配则返回 null*/public Coffee createCoffee(String type) {if ("americano".equalsIgnoreCase(type)) {return new Americano();} else if ("mocha".equalsIgnoreCase(type)) {return new Mocha();} else if ("cappuccino".equalsIgnoreCase(type)) {return new Cappuccino();}return null;}
}
基础版通过传入字符串参数来决定创建的咖啡产品类型,但这种方式易出现参数输入错误的情况,且新增产品时需在工厂类中添加额外的判断逻辑。
(二)升级版
// 咖啡产品的接口
public interface Coffee {void make();
}// 美式咖啡类,实现 Coffee 接口
public class Americano implements Coffee {@Overridepublic void make() {System.out.println("正在制作美式咖啡");}
}// 摩卡咖啡类,实现 Coffee 接口
public class Mocha implements Coffee {@Overridepublic void make() {System.out.println("正在制作摩卡咖啡");}
}// 卡布奇诺咖啡类,实现 Coffee 接口
public class Cappuccino implements Coffee {@Overridepublic void make() {System.out.println("正在制作卡布奇诺咖啡");}
}// 简单工厂类(升级版)
public class CoffeeSimpleFactory {/*** 使用反射根据传入的咖啡类的 Class 对象创建对应的咖啡对象* @param clazz 咖啡类的 Class 对象* @return 对应的咖啡对象,如果 clazz 为 null 则返回 null* @throws Exception 反射创建对象时可能抛出的异常*/public static Coffee createCoffee(Class<? extends Coffee> clazz) throws Exception {if (clazz!= null) {return clazz.newInstance();}return null;}
}
升级版利用反射机制解决了基础版的参数准确性和扩展性问题。
(三)总结
适用场景:
- 工厂负责创建的对象数量相对较少。
- 客户端只需提供参数,无需关注对象创建的具体流程。
优点:
- 只需传入准确参数,即可轻松获取所需对象,无需知晓内部创建细节。
缺点:
- 工厂类承担过多职责,新增产品类型时需修改判断逻辑,违背了开闭原则。
- 面对复杂的产品结构时,扩展难度较大。
二、工厂方法模式
工厂方法模式明确了一个创建对象的接口,具体由实现该接口的子类来决定实例化的对象类别,将对象的实例化操作推迟至子类中进行。
(一)主要角色
- 抽象工厂(Abstract Factory):定义创建产品的通用接口,为调用者提供访问具体工厂方法的途径,以创建产品。
- 具体工厂(Concrete Factory):负责实现抽象工厂中的抽象方法,从而完成具体产品的创建工作。
- 抽象产品(Product):确立产品的规范和标准,详细描述产品的主要特性与功能。
- 具体产品(Concrete Product):切实实现抽象产品所定义的接口,由具体工厂负责创建,且与具体工厂之间存在一一对应的关系。
(二)代码实现
// 抽象工厂
public interface CoffeeFactory {/*** 创建咖啡对象* @return 抽象的咖啡对象*/Coffee create();
}// 具体工厂 - 拿铁咖啡工厂
public class LatteFactory implements CoffeeFactory {@Overridepublic Coffee create() {return new Latte();}
}// 抽象产品
public interface Coffee {/*** 描述咖啡的制作过程*/void make();
}// 具体产品 - 拿铁咖啡
public class Latte implements Coffee {@Overridepublic void make() {System.out.println("精心调配拿铁咖啡,牛奶与咖啡的完美融合");}
}
(三)总结
适用场景:
- 当创建对象的过程涉及大量重复的代码时。
- 客户端(应用层)不关心产品类实例的创建和实现细节,只关注最终获取到的产品功能。
- 当一个父类通过其子类来决定创建具体的对象类型时。
优点:
- 用户只需关注所需产品对应的具体工厂,无需操心产品的创建细节。
- 新增产品时,符合开闭原则,只需创建新的具体工厂和具体产品类,无需修改现有代码,提高了系统的可扩展性。
缺点:
- 随着产品种类的增加,类的数量会显著增多,导致代码结构的复杂度上升。
- 较高的抽象层次增加了系统的抽象性,对于初学者或不熟悉设计模式的开发者来说,理解和运用的难度较大。
三、抽象工厂模式
抽象工厂模式旨在提供一个创建一系列相关或相互依赖对象的接口,而无需明确指定具体的类。
(一)主要角色
- 抽象工厂(Abstract Factory):提供了创建多个不同产品的接口,这些产品可能属于不同的等级或类别。
- 具体工厂(Concrete Factory):实现了抽象工厂中的抽象方法,负责生成具体的一组相关或相互依赖的产品。
- 抽象产品(Product):定义了产品的基本规范和主要特性,一个抽象工厂可能关联多个不同的抽象产品。
- 具体产品(Concrete Product):实现了抽象产品所定义的接口,由具体的工厂进行创建,且与具体工厂之间存在多对一的关系。
(二)代码实现
// 咖啡店 抽象工厂
public interface CoffeeShopFactory {/*** 创建咖啡产品* @return 具体的咖啡产品*/Coffee createCoffee();/*** 创建甜点产品* @return 具体的甜点产品*/Dessert createDessert();
}// 美式风格工厂
public class AmericanFactory implements CoffeeShopFactory {@Overridepublic Coffee createCoffee() {return new Americano();}@Overridepublic Dessert createDessert() {return new Cheesecake();}
}// 意式风格工厂
public class ItalyFactory implements CoffeeShopFactory {@Overridepublic Coffee createCoffee() {return new Cappuccino();}@Overridepublic Dessert createDessert() {return new Tiramisu();}
}// 抽象产品 - 咖啡
public interface Coffee {/*** 描述咖啡的制作过程*/void make();
}// 具体产品 - 美式咖啡
public class Americano implements Coffee {@Overridepublic void make() {System.out.println("精心调制美式咖啡,浓郁醇厚");}
}// 抽象产品 - 甜点
public interface Dessert {/*** 描述甜点的品尝方式*/void enjoy();
}// 具体产品 - 芝士蛋糕
public class Cheesecake implements Dessert {@Overridepublic void enjoy() {System.out.println("尽情享受美味的芝士蛋糕,香甜可口");}
}
(三)总结
产品族:指一系列紧密相关、相互关联的产品集合。
产品等级:指处于同一继承体系或具有相似性质的产品类别。
适用场景:
- 当客户端(应用层)不依赖于产品类实例的创建和实现细节时。
- 强调一系列相关的产品对象(属于同一产品族)需协同工作,且创建这些对象的过程存在大量重复代码时。
- 当需要为客户端提供一个统一的产品类库,使所有产品以相同的接口呈现,从而降低客户端对具体实现的依赖时。
优点:
- 能够确保当一个产品族中的多个对象协同工作时,客户端始终使用来自同一产品族的对象,保证了产品的一致性和协调性。
缺点:
- 当产品族中需要新增一个产品时,所有相关的工厂类都需要进行修改,这可能导致较大的代码改动和潜在的风险。
相关文章:
《工厂模式在软件开发中的深度剖析与应用》
工厂模式 在软件开发的领域中,设计模式充当着解决常见问题的高效且可复用的策略角色。其中,工厂模式作为创建对象的重要设计模式,具有不可小觑的应用价值。接下来,我们将深入探讨简单工厂模式、工厂方法模式和抽象工厂模式。 一…...
双向通信之Websocket
介绍 Websocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP协议不同,websocket允许客户端与服务器之间的双向通信,可以在同一条连接上进行多次消息的快速传递。我之前在做一个线上刷题网站的时候,需要设计一个社区讨论模块&am…...
git学习使用碰到的问题1
本来在B站上看到的关于stash的使用时视频末尾讲到git stash drop 编号 会删除暂存记录 确实也是这么回事,但是末尾说到git stash pop 编号时up主说在恢复工作进度的时候我们可以直接删除掉这个工作记录可以直接使用 git stash pop stash{0} 使用完以后却出现了如上图…...
JavaScript初级——Math
一、Math 和其他的对象不同,它不是一个构造函数。它属于一个工具类,不用创建对象,里边封装了数学运算相关的属性和方法。 比如: Math.PI 表示圆周率。 二、Math.abs() —— 可以用来计算一个数的绝对值。 三…...
ffmpeg的基础命令
文章目录 ffmpeg/ffplay/ffprobe区别ffmpeg 的作用ffplay的作用ffprobe的作用 ffmpeg使用概述功能概述转码过程简单使用FFMPEG -i常用的 -i例子 ff***工具之间共享的选项ffmpeg主要选项ffmpeg提取音视频数据ffmpeg命令修改原有的视频格式ffmpeg命令裁剪和合并视频拼接视频的方式…...
二建机电工程实务试题内附答案
1.下列有色金属材料中,不属于铜合金的是()。 A.紫铜 B.青铜 C.黄铜 D.白铜【答案】A 2.用于完成介质间热量交换的换热设备是()。 A.分离器 B.反应器 C.冷凝器 D.分解锅【答案】C 3.工程测量的核心是()。 A.测量精度 B.设计要求 C.减少误差累积 D.检核【答案】D 4.吊…...
Redis的热key以及Big(大)key是什么?如何解决Redis的热key以及Big(大)key问题?
一、先讲讲什么是redis的热key问题 在Redis中,我们把访问频率高的Key,称为热Key。比如突然有几十万的请求去访问redis中某个特定的Key,那么这样会造成redis服务器短时间流量过于集中,很可能导致redis的服务器宕机。那么接下来对这…...
django学习入门系列之第九点《MySQL命令介绍一》
文章目录 MySQL命令数据库的管理(文件夹)查看现在已有的数据库(文件夹)创建数据库(文件夹)删除数据库(文件夹)进入数据库(文件夹)查看文件夹下所有的数据表&a…...
Mysql面试一
目录 一、事务的四大特性(ACID): 脏读 不可重复读 幻读 隔离性与隔离级别 数据库的三大范式 第一范式。确保数据表中的每个字段都是不可分割的最小单位,即原子性。这意味着表中的每一列都应代表一个独立的数据单元ÿ…...
模型优化之剪枝
文章目录 什么是神经网络剪枝剪枝的好处不同粒度的剪枝剪枝的分类非结构化剪枝结构化剪枝 哪些层的参数更容易被剪掉剪枝效果 什么是神经网络剪枝 神经网络剪枝 在训练期间删除连接密集张量将变得稀疏(用零填充)可以通过结构化块( n m nm nm&…...
JVM的组成
JVM 运行在操作系统之上 java二进制字节码文件的运行环境 JVM的组成部分 java代码在编写完成后编译成字节码文件通过类加载器 来到运行数据区,主要作用是加载字节码到内存 包含 方法区/元空间 堆 程序计数器,虚拟机栈,本地方法栈等等 随后来到执行引擎,主要作用是翻译字…...
快速上手 iOS Protocol Buffer
快速上手 iOS Protocol Buffer | 来自缤纷多彩的灰 本文主要介绍在 iOS 开发中如何快速上手使用 Protobuf。更多关于 Protobuf 的介绍和相关的功能 api,读者可自行查阅官网。 Protocol Buffer(简称 Protobuf)是一种由Google开发的语言中立、…...
每天一个数据分析题(四百八十)- 线性回归建模
关于线性回归建模,线性回归模型假设说法不正确的是? A. 因变量和自变量要有因果关系 B. 残差均值为0 C. 残差服从正态分布 D. 自变量不存在共线性 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专…...
电动汽车和混动汽车DC-DC转换器的创新设计与测试方法
汽车 DC-DC 转换器市场规模将达到187亿美元,年复合增长率为10%。 DC-DC 转换器是汽车的重要组成部分,它可以通过电压转换为各种车载系统供电,例如日益复杂的车载信息娱乐系统、使用驾驶辅助系统(ADAS)实现的增强安全功…...
OriginPro快速上手指南:数据可视化与分析的利器
目录 OriginLab - Origin and OriginPro - Data Analysis and Graphing Softwarehttps://www.originlab.com/编辑 一、安装与界面概览 安装 界面概览 二、基础操作 数据输入 创建图表 三、高级功能 数据分析 自动化与脚本 Origin 提供了几个小工具 四、技巧与提示…...
缓存学习
缓存基本概念 概念 对于缓存,最普遍的理解是能让打开某些页面速度更快的工具。从技术角度来看,其本质上是因为缓存是基于内存建立的,而内存的读写速度相比之于硬盘快了xx倍,因此用内存来代替硬盘作为读写的介质当然能大大提高访…...
亚世光电:消费电子年度表演
机圈风云再起,消费电子乘风而起? 今天我们来聊——亚世光电 最近,华为mate60突然降价,被大家怀疑是为新品上市做准备,算算时间,下半年的消费电子大战也即将拉开帷幕,而亚世光电所在的光电显示领…...
AI 工程应用 建筑表面检测及修复
文章目录 1 项目概述(必写):2 技术方案与实施步骤2.1 模型选择(必写):2.2 数据的构建:2.3 功能整合(进阶): 3 实施步骤:3.1 环境搭建(…...
Qt-Qt中的小事项(7)
目录 命名风格 快捷键 查询文档 坐标系 代码理解 move 命名风格 这个也是老生常谈的问题了,入乡随俗就好啦 快捷键 这里是一些常用的快捷键,用多了自然就熟悉了 • 注释:ctrl/ • 运行:ctrlR • 编译:ctrlB …...
Android MediaRecorder 视频录制及报错解决
目录 一、start failed: -19 二、使用MediaRecorder录制视频 2.1 申请权限 2.2 布局文件 2.3 MediaRecordActivity 2.4 运行结果 三、拓展 3.1 录制视频模糊(解决) 3.2 阿里云OSS上传文件 3.2.1 权限(刚需) 3.2.2 安装SDK 3.2.3 使用 相关链接 一、start failed…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
2.2.2 ASPICE的需求分析
ASPICE的需求分析是汽车软件开发过程中至关重要的一环,它涉及到对需求进行详细分析、验证和确认,以确保软件产品能够满足客户和用户的需求。在ASPICE中,需求分析的关键步骤包括: 需求细化:将从需求收集阶段获得的高层需…...
二叉树-144.二叉树的前序遍历-力扣(LeetCode)
一、题目解析 对于递归方法的前序遍历十分简单,但对于一位合格的程序猿而言,需要掌握将递归转化为非递归的能力,毕竟递归调用的时候会调用大量的栈帧,存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧,而非…...
若依项目部署--传统架构--未完待续
若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加,传统开发模式存在效率低,重复劳动多等问题。若依项目通过整合主流技术框架&…...
docker容器互联
1.docker可以通过网路访问 2.docker允许映射容器内应用的服务端口到本地宿主主机 3.互联机制实现多个容器间通过容器名来快速访问 一 、端口映射实现容器访问 1.从外部访问容器应用 我们先把之前的删掉吧(如果不删的话,容器就提不起来,因…...
开源项目实战学习之YOLO11:12.6 ultralytics-models-tiny_encoder.py
👉 欢迎关注,了解更多精彩内容 👉 欢迎关注,了解更多精彩内容 👉 欢迎关注,了解更多精彩内容 ultralytics-models-sam 1.sam-modules-tiny_encoder.py2.数据处理流程3.代码架构图(类层次与依赖)blocks.py: 定义模型中的各种模块结构 ,如卷积块、残差块等基础构建…...
