设计模式-创建型模式-(工厂、简单工厂、抽象工厂)
一、简单工厂模式
上代码
public class FoodFactory {public static Food makeFood(String name) {if (name.equals("noodle")) {Food noodle = new LanZhouNoodle();noodle.addSpicy("more");return noodle;} else if (name.equals("chicken")) {Food chicken = new HuangMenChicken();chicken.addCondiment("potato");return chicken;} else {return null;}}
}
二、工厂模式
简单工厂模式很简单,如果它能满足我们的需要,我觉得就不要折腾了。之所以需要引入工厂模式,是因为我们往往需要使用两个或两个以上的工厂
public interface FoodFactory {Food makeFood(String name);
}
public class ChineseFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new ChineseFoodA();} else if (name.equals("B")) {return new ChineseFoodB();} else {return null;}}
}
public class AmericanFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new AmericanFoodA();} else if (name.equals("B")) {return new AmericanFoodB();} else {return null;}}
}
其中,ChineseFoodA、ChineseFoodB、AmericanFoodA、AmericanFoodB 都派生自 Food
客户端调用:
public class APP {public static void main(String[] args) {// 先选择一个具体的工厂FoodFactory factory = new ChineseFoodFactory();// 由第一步的工厂产生具体的对象,不同的工厂造出不一样的对象Food food = factory.makeFood("A");}
}
虽然都是调用 makeFood("A") 制作 A 类食物,但是,不同的工厂生产出来的完全不一样。
第一步,我们需要选取合适的工厂,然后第二步基本上和简单工厂一样。
核心在于,我们需要在第一步选好我们需要的工厂。比如,我们有 LogFactory 接口,实现类有 FileLogFactory 和 KafkaLogFactory,分别对应将日志写入文件和写入 Kafka 中,显然,我们客户端第一步就需要决定到底要实例化 FileLogFactory 还是 KafkaLogFactory,这将决定之后的所有的操作。
虽然简单,不过我也把所有的构件都画到一张图上,这样读者看着比较清晰:

三、抽象工厂模式
当涉及到产品族的时候,就需要引入抽象工厂模式了。
一个经典的例子是造一台电脑。我们先不引入抽象工厂模式,看看怎么实现。
因为电脑是由许多的构件组成的,我们将 CPU 和主板进行抽象,然后 CPU 由 CPUFactory 生产,主板由 MainBoardFactory 生产,然后,我们再将 CPU 和主板搭配起来组合在一起,如下图:

这个时候的客户端调用是这样的:
// 得到 Intel 的 CPU
CPUFactory cpuFactory = new IntelCPUFactory();
CPU cpu = intelCPUFactory.makeCPU();// 得到 AMD 的主板
MainBoardFactory mainBoardFactory = new AmdMainBoardFactory();
MainBoard mainBoard = mainBoardFactory.make();// 组装 CPU 和主板
Computer computer = new Computer(cpu, mainBoard);
单独看 CPU 工厂和主板工厂,它们分别是前面我们说的工厂模式。这种方式也容易扩展,因为要给电脑加硬盘的话,只需要加一个 HardDiskFactory 和相应的实现即可,不需要修改现有的工厂。
但是,这种方式有一个问题,那就是如果 Intel 家产的 CPU 和 AMD 产的主板不能兼容使用,那么这代码就容易出错,因为客户端并不知道它们不兼容,也就会错误地出现随意组合。
下面就是我们要说的产品族的概念,它代表了组成某个产品的一系列附件的集合:
当涉及到这种产品族的问题的时候,就需要抽象工厂模式来支持了。我们不再定义 CPU 工厂、主板工厂、硬盘工厂、显示屏工厂等等,我们直接定义电脑工厂,每个电脑工厂负责生产所有的设备,这样能保证肯定不存在兼容问题。

这个时候,对于客户端来说,不再需要单独挑选 CPU厂商、主板厂商、硬盘厂商等,直接选择一家品牌工厂,品牌工厂会负责生产所有的东西,而且能保证肯定是兼容可用的。
public static void main(String[] args) {// 第一步就要选定一个“大厂”ComputerFactory cf = new AmdFactory();// 从这个大厂造 CPUCPU cpu = cf.makeCPU();// 从这个大厂造主板MainBoard board = cf.makeMainBoard();// 从这个大厂造硬盘HardDisk hardDisk = cf.makeHardDisk();// 将同一个厂子出来的 CPU、主板、硬盘组装在一起Computer result = new Computer(cpu, board, hardDisk);
}
当然,抽象工厂的问题也是显而易见的,比如我们要加个显示器,就需要修改所有的工厂,给所有的工厂都加上制造显示器的方法。这有点违反了对修改关闭,对扩展开放这个设计原则。
相关文章:
设计模式-创建型模式-(工厂、简单工厂、抽象工厂)
一、简单工厂模式 上代码 public class FoodFactory {public static Food makeFood(String name) {if (name.equals("noodle")) {Food noodle new LanZhouNoodle();noodle.addSpicy("more");return noodle;} else if (name.equals("chicken")…...
JAVA12新特性
JAVA12新特性 概述 2019年3月19日,java12正式发布了,总共有8个新的JEP(JDK Enhancement Proposals) JDK 12 is the open-source reference implementation of version 12 of the Java SE12 Platform as specified by by JSR 386 in the Java Community Process. JDK 12 reac…...
Nginx 静态文件、反向代理、负载均衡、缓存、SSL/TLS 加密、gzip 压缩 等等
Nginx的功能 1. 静态文件服务器2. 反向代理服务器3. 负载均衡4. 缓存5. SSL/TLS 加密6. URL 重写7. HTTP/28. WebSocket9. 反向代理缓存10. 安全限制11. gzip 压缩12. 请求限速13. 日志记录14. SSL 证书续订 Nginx 是一个高性能的开源 Web 服务器和反向代理服务器,它…...
Linux设备驱动模型(一)
一、sysfs文件系统 sysfs是一个虚拟文件系统,将内核总的设备对象的链接关系,以文件目录的方式表示出来,并提对设备提供读写接口。 二、kobject kobject是内核中对象表示的基类,可以认为所有的内核对象都是一个kobject kobject单…...
【Python入门篇】——Python基础语法(标识符与运算符)
作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: Python入门,本专栏主要内容为Python的基础语法,Python中的选择循环语句…...
扩展 VirtualBox 已分配磁盘的方法
扩展 VirtualBox 已分配磁盘的方法 第一步:用VirtualBox命令行调整已分配磁盘的大小第二步:用windows磁盘管理工具扩展磁盘空间其他无关配置如何选择虚拟机的芯片组 注意:扩展操作只支持 vdi 格式的磁盘,就是VirtualBox自己的磁盘…...
【LeetCode】646. 最长数对链
646. 最长数对链(中等) 思路 这道题和 300. 最长递增子序列 类似,我们可以定义 dp 数组,其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个位置后,统计一遍各个位置的结果即可得到题目要求的结果。 但是题目中强…...
Makefile教程(Makefile的结构)
文章目录 前言一、Makefile的结构二、深入案例三、Makefile中的一些技巧总结 前言 一、Makefile的结构 Makefile 通常由一系列规则组成,每条规则定义了如何从源文件生成目标文件。每个规则又由目标、依赖和命令三部分组成。 下面是 Makefile 规则的基本结构&…...
SpringMVC(后)SSM整合
10、文件上传和下载 10.1、文件下载 ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文 使用ResponseEntity实现下载文件的功能 RequestMapping("/testDown") public ResponseEntity<byte[]> testResp…...
【博弈论】【第一章】博弈论导论
博弈论导论 【例题】选择数字【例题】巴什博弈【例题】射手博弈博弈论的基本概念:参与人战略行动信息支付函数【例题】分100元 课程概述: 【例题】选择数字 两个参与人A和B,轮流选择[3,4,5,6,7,8,9]中的一个整数(可重复)。当累计…...
keil移植linux(makefile)
文章目录 运行环境:1.1 freeRTOS_LED工程移植1)修改cubeMX配置2)setting设置3)launch设置4)修改makefile5)修改代码6)实验效果 运行环境: ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6 stlink 9-24v可调电源 robomaster A 板 1.1 freeRTOS_L…...
C++——类和对象(3)
作者:几冬雪来 时间:2023年5月6日 内容:C类和对象内容讲解 目录 前言: 1.运算符重载(续): 2.赋值重载: 结尾: 前言: 在上一篇博客中我们再一次讲解了…...
itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析
《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录 生产者属性#clock-cells 属性clock-output-namesclock-frequencyassigned-clockclock-indicesassigned-clock-parents 消费者属性 设备树中的时钟信息以时钟树形式体现,时钟树包括时钟的属性和结…...
linux中使用docker部署微服务
目录 一、制作jar包(如果看一眼很简单,可以直接使用结尾的jar) 1.首先创建一个微服务 demo2 2.启动微服务(在DemoApplication上右键执行启动就行) 注意:其他操作导致的 可能遇到的报错 3.修改端口 4.新…...
操作系统考试复习—第三章 优先级倒置 死锁问题
当前OS广泛采用优先级调度算法和抢占方式,然而在系统中存在着影响进程运行的资源从而可能产生"优先级倒置"现象 具体解释为:在原本的调度算法设计中,高优先级进程可以抢占低优先级的CPU资源,先执行高优先级任务。但是存…...
OpenHarmony送显流程分析
OpenHarmony送显流程分析 引言 本文档主要记录OpenHarmony在渲染完成之后如何进行合成和送显流程的。这个过程牵涉的代码很多,而且流程也是比较繁琐的。所以我一定要坚持下来。千万不能半途而废,也不要想着一口气吃出一个胖子,路漫漫其修远兮…...
Java面试题字节流字符流
String 编码UTF-8 和GBK的区别 GBK编码:是指中国的中文字符,其实它包含了简体中文与繁体中文字符,另外还有一种字符 “gb2312”,这种字符仅能存储简体中文字符。 UTF-8编码:它是一种全国家通过的一种编码&#x…...
Self-Attention结构细节及计算过程
一、结构 上面那个图其实不是那么重要,只要知道将输入的x矩阵转换成三个矩阵进行计算即可。自注意力结构的输入为 输入矩阵的三个变形 Q(query矩阵)、K(key矩阵)、V(value矩阵)构成,…...
在Ubuntu18.04中安装uWebSockets库
目录 1.下载uWebSockets库2.下载uSockets3.安装openssl开发包4.编译首先说明这里使用的Ubuntu版本为18.04。 1.下载uWebSockets库 下载uWebSockets库有两种方式,一是终端,从Github中克隆uWebSockets库到Ubuntu本地文件夹,二是打开uWebSockets库下载链接自己下载到Windows,然…...
【Fluent】接着上一次计算的结果继续计算,利用计算过程中得到的物理场(温度、速度、压力等)插值Interpolate文件初始化模型的方法
一、问题背景 因为fluent中支持的初始化无非三种类型。 1、Standard initialization 标准初始化 2、Hybridinitialization 混合初始化 3、FMG initialization FMG初始化 另外,还可以用UDF通过坐标判断的方式予以初始化。 但是这些初始化方法都没办法利用以前计算过…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
