【Spring6】| GoF之工厂模式
目录
一:GoF之工厂模式
1. 工厂模式的三种形态
2. 简单工厂模式
3. 工厂方法模式
4. 抽象工厂模式(了解)
一:GoF之工厂模式
(1)GoF(Gang of Four),中文名——四人组。
(2)设计模式:一种可以被重复利用的解决方案。
(3)《Design Patterns: Elements of Reusable Object-Oriented Software》(即《设计模式》一书),1995年由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著。这几位作者常被称为"四人组(Gang of Four)"。
(4)该书中描述了23种设计模式,我们平常所说的设计模式就是指这23种设计模式;不过除了GoF23种设计模式之外,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式、MVC模式等)!
GoF23种设计模式可分为三大类:
创建型(5个):解决对象创建问题
- 单例模式
- 原型模式
- 建造者模式
- 抽象工厂模式
- 工厂方法模式
结构型(7个):一些类或对象组合在一起的经典结构
- 代理模式
- 桥接模式
- 外观模式
- 享元模式
- 组合模式
- 适配器模式
- 装饰模式
行为型(11个):解决类或对象之间的交互问题
- 策略模式
- 解释器模式
- 中介者模式
- 访问者模式
- 状态模式
- 备忘录模式
- 命令模式
- 迭代子模式
- 观察者模式
- 责任链模式
- 模板方法模式
1. 工厂模式的三种形态
(1)工厂模式是解决对象创建问题的,所以工厂模式属于创建型设计模式!这里为什么学习工厂模式呢?这是因为Spring框架底层使用了大量的工厂模式!
(2)工厂模式通常有三种形态:
- 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。
- 第二种:工厂方法模式(Factory Method):是23种设计模式之一。
- 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一。
2. 简单工厂模式
(1)简单工厂模式是工厂方法模式的一种特殊实现,又被称为:静态工厂方法模式!
(2)简单工厂模式的角色包括三个:
- 抽象产品 角色
- 具体产品 角色
- 工厂类 角色
抽象产品 角色
Weapon武器类
package com.bjpowernode.simple.factory;// 抽象产品角色
public abstract class Weapon {// 所有的武器都可以攻击。 public abstract void attack();
}
具体产品 角色
Tank坦克类
package com.bjpowernode.simple.factory;// 具体产品角色
public class Tank extends Weapon{@Overridepublic void attack() {System.out.println("坦克开炮!!!");}
}
Fighter战斗机类
package com.bjpowernode.simple.factory;// 具体产品角色
public class Fighter extends Weapon{@Overridepublic void attack() {System.out.println("战斗机抛下小男孩!!!!");}
}
Dagger匕首类
package com.bjpowernode.simple.factory;// 具体产品角色
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("砍丫的!!!");}
}
工厂类 角色
WeaponFactory武器工厂类
①是静态方法,要获取什么产品?就看你传什么参数,传TANK获取坦克,传DAGGER获取匕首,传FIGHTER获取战斗机
②简单工厂模式中有一个静态方法,所以被称为:静态工厂方法模式。
package com.bjpowernode.simple.factory;// 工厂类角色
public class WeaponFactory {public static Weapon get(String weaponType){if ("TANK".equals(weaponType)) {return new Tank();} else if ("DAGGER".equals(weaponType)) {return new Dagger();} else if ("FIGHTER".equals(weaponType)) {return new Fighter();} else {throw new RuntimeException("不支持该武器的生产");}}}
客户端程序---进行测试
①对于客户端来说,坦克的生产细节(创建对象),并不需要关心,只需要向工厂索要即可!
②简单工厂模式达到了什么呢?职责分离,客户端不需要关心产品的生产细节;客户端只负责消费,工厂类负责生产;一个负责生产,一个负责消费;生产者和消费者分离了,这就是简单工厂模式的作用。
package com.bjpowernode.simple.factory;// 这是客户端程序
public class Test {public static void main(String[] args) {// 需要坦克Weapon tank = WeaponFactory.get("TANK");tank.attack();// 需要匕首Weapon dagger = WeaponFactory.get("DAGGER");dagger.attack();// 需要战斗机Weapon fighter = WeaponFactory.get("FIGHTER");fighter.attack();}
}
总结:Spring中的BeanFactory就使用了简单工厂模式!
(1)简单工厂模式解决什么问题(优点)呢?
客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”;生产和消费分离!(2)简单工厂模式的缺点?
①假设现在需要扩展一个新的武器产品,WeaponFactory工厂类的代码是需要修改的,显然违背了OCP原则!
②工厂类的责任比较重大,不能出现任何问题,因为这个工厂类负责所有产品的生产,称为全能类,或者叫做上帝类。这个工厂类一旦出问题,整个系统必然全部瘫痪!
3. 工厂方法模式
(1)工厂方法模式可以解决简单工厂模式当中的OCP问题。怎么解决的?一个工厂对应生产一种产品;这样工厂就不是全能类了,不是上帝类了;另外,也可以符合OCP原则。
(2)工厂方法模式的角色包括四个:
- 抽象产品 角色
- 具体产品 角色
- 抽象工厂 角色
- 具体工厂 角色
抽象工厂 角色
package com.bjpowernode.factory.method;public abstract class WeaponFactory {// 这个方法不是静态的,是实例方法。public abstract Weapon get();}
具体工厂 角色---继承抽象工厂,一个工厂对应生产一种产品
DaggerFactory生产匕首的专有工厂
package com.bjpowernode.factory.method;// 具体工厂角色
public class DaggerFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Dagger();}
}
TankFactory生产坦克的专有工厂
package com.bjpowernode.factory.method;// 具体工厂角色
public class TankFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Tank();}
}
客户端程序---进行测试
注:这里还是创建对象了,所以我们使用上面的简单工厂模式在抽象出一个大工厂,来管理创建对象的问题!这里暂时只考虑结局OCP的问题!
package com.bjpowernode.factory.method;// 客户端程序
public class Test {public static void main(String[] args) {WeaponFactory weaponFactory = new DaggerFactory();Weapon dagger = weaponFactory.get();dagger.attack();WeaponFactory weaponFactory1 = new TankFactory();Weapon gun = weaponFactory1.get();gun.attack();}
}
总结:
(1)工厂方法模式的缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂类,使得系统中类的个数成倍增加(存在类爆炸问题),在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖!(2)工厂方法模式的优点:
①当你扩展一个产品的时候,符合OCP原则(扩展性高),因为只需要添加两个类,一个类是具体产品类,一个类是具体工厂类,都是添加类,没有修改之前的代码,所以符合OCP!
②一个调用者想创建一个对象,只要知道其名称就可以了,屏蔽产品的具体实现,调用者只关心产品的接口。
4. 抽象工厂模式(了解)
(1)Spring底层并没有调用抽象工厂模式,所以这部分可以暂时为了解!
(2)抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类!
(3)抽象工厂模式特点:
①抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。
②抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。
③抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
④它有多个抽象产品类,每个抽象产品类可以派生出多个具体产品类,一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。
⑤每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结果。
(4)抽象工厂中包含4个角色:
- 抽象产品角色
- 具体产品角色
- 抽象工厂角色
- 具体工厂角色

第一部分:武器产品
Weapon类武器产品族
package com.powernode.product;// 武器产品族
public abstract class Weapon {// 所有武器都可以攻击public abstract void attack();
}
Gun类武器产品族中的产品等级1
package com.powernode.product;// 武器产品族中的产品等级1
public class Gun extends Weapon{@Overridepublic void attack() {System.out.println("开枪射击!");}
}
Dagger类武器产品族中的产品等级2
package com.powernode.product;// 武器产品族中的产品等级2
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("砍丫的!");}
}
第二部分:水果产品
Fruit类水果产品族
package com.powernode.product;// 水果产品族
public abstract class Fruit {// 所有果实都有一个成熟周期。 public abstract void ripeCycle();
}
Orange类水果产品族中的产品等级1
package com.powernode.product;// 水果产品族中的产品等级1
public class Orange extends Fruit{@Overridepublic void ripeCycle() {System.out.println("橘子的成熟周期是10个月");}
}
Apple类水果产品族中的产品等级2
package com.powernode.product;// 水果产品族中的产品等级2
public class Apple extends Fruit{@Overridepublic void ripeCycle() {System.out.println("苹果的成熟周期是8个月");}
}
第三部分:抽象工厂类
package com.powernode.factory;import com.powernode.product.Fruit;
import com.powernode.product.Weapon;// 抽象工厂
public abstract class AbstractFactory {// 两个实例方法public abstract Weapon getWeapon(String type);public abstract Fruit getFruit(String type);
}
第四部分:具体工厂类
武器族工厂
package com.powernode.factory;import com.powernode.product.Dagger;
import com.powernode.product.Fruit;
import com.powernode.product.Gun;
import com.powernode.product.Weapon;// 武器族工厂
public class WeaponFactory extends AbstractFactory{public Weapon getWeapon(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Gun".equals(type)) {return new Gun();} else if ("Dagger".equals(type)) {return new Dagger();} else {throw new RuntimeException("无法生产该武器");}}@Overridepublic Fruit getFruit(String type) {return null;}
}
水果族工厂
package com.powernode.factory;import com.powernode.product.*;// 水果族工厂
public class FruitFactory extends AbstractFactory{@Overridepublic Weapon getWeapon(String type) {return null;}public Fruit getFruit(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Orange".equals(type)) {return new Orange();} else if ("Apple".equals(type)) {return new Apple();} else {throw new RuntimeException("果园不产这种水果");}}
}
第五部分:客户端程序
package com.powernode.client;import com.powernode.factory.AbstractFactory;
import com.powernode.factory.FruitFactory;
import com.powernode.factory.WeaponFactory;
import com.powernode.product.Fruit;
import com.powernode.product.Weapon;public class Client {public static void main(String[] args) {// 客户端调用方法时只面向AbstractFactory调用方法。AbstractFactory factory = new WeaponFactory(); // 注意:这里的new WeaponFactory()可以采用 简单工厂模式 进行隐藏。Weapon gun = factory.getWeapon("Gun");Weapon dagger = factory.getWeapon("Dagger");gun.attack();dagger.attack();AbstractFactory factory1 = new FruitFactory(); // 注意:这里的new FruitFactory()可以采用 简单工厂模式 进行隐藏。Fruit orange = factory1.getFruit("Orange");Fruit apple = factory1.getFruit("Apple");orange.ripeCycle();apple.ripeCycle();}
}
总结:
(1)优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
(2)缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在AbstractFactory里加代码,又要在具体的里面加代码。
相关文章:
【Spring6】| GoF之工厂模式
目录 一:GoF之工厂模式 1. 工厂模式的三种形态 2. 简单工厂模式 3. 工厂方法模式 4. 抽象工厂模式(了解) 一:GoF之工厂模式 (1)GoF(Gang of Four),中文名——四人组…...
初识Node.js
文章目录初识Node.jsNode.js简介fs模块演示路径问题path路径模块http模块创建web服务器得基本步骤req请求对象res响应对象解决中文乱码问题模块化的基本慨念1、模块化2、Node.js中模块的分类3、Node.js中的模块作用域3.1什么是模块作用域4、向外共享模块作用域中的成员4.1modul…...
C51---软件消抖
1.example #include "reg52.h" #include "intrins.h" //main.c(11): error C264: intrinsic _nop_: declaration/activation error,添加这个头文件就可了 sbit led1 P3^7;//引脚位置,根据原理图可知 sbit key1 P2^1; sbit key2 P2^0; void …...
redis数据持久化
redis备份概念 Redis所有数据都是保存在内存中,Redis数据备份可以定期的通过异步方式保存到磁盘上,该方式称为半持久化模式,如果每一次数据变化都写入aof文件里面,则称为全持久化模式。同时还可以基于Redis主从复制实现Redis备份…...
Java StringBuffer类
Java StringBuffer类是Java语言中一个非常重要的类,它提供了丰富的方法,可以方便地进行字符串操作。本文将详细介绍Java StringBuffer类的作用以及在实际工作中的用途。 StringBuffer类的作用 Java StringBuffer类是一个可变的字符串缓冲区,…...
电路模型和电路定律(2)——“电路分析”
各位CSDN的uu们你们好呀,好久没有更新电路分析的文章啦,今天来小小复习一波,之前那篇博客,小雅兰更新了电路的历史以及电压电流的参考方向,这篇博客小雅兰继续!!! 电阻元件 电压源和…...
天琊超级进程监视器的应用试验(19)
实验目的 1、了解进程概念及其基本原理; 2、掌握天琊超级进程监视器的安装与使用。预备知识 本实验要求实验者具备如下的相关知识。 操作系统的安全配置是整个系统安全审计策略核心,其目的就是从系统根源构筑安全防护体系,通过用户的一…...
使用 Pulumi 打造自己的多云管理平台
前言在公有云技术与产品飞速发展的时代,业务对于其自身的可用性提出了越来越高的要求,当跨区域容灾已经无法满足业务需求的情况下,我们通常会考虑多云部署我们的业务平台,以规避更大规模的风险。但在多云平台部署的架构下…...
什么是MyBatis?无论是基础教学还是技术精进,你都应该看这篇MyBatis
文章目录学习之前,跟你们说点事情,有助于你能快速看完文章一、先应用再学习,代码示例1. 第一个MyBatis程序2. MyBatis整合Spring3. SpringBoot整合MyBatis二、MyBatis整体流程,各组件的作用域和生命周期三、说说MyBatis-config.xm…...
【编程基础之Python】10、Python中的运算符
【编程基础之Python】10、Python中的运算符Python中的运算符算术运算符赋值运算符比较运算符逻辑运算符位运算符成员运算符身份运算符运算符优先级运算符总结Python中的运算符 Python是一门非常流行的编程语言,它支持各种运算符来执行各种操作。这篇文章将详细介绍…...
Android的基础介绍
一、Android介绍 Android是一种基于Linux的自由及开放源代码的操作系统,Android 分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和Linux内核层。 Android 是Google开发的基于Linux平台的开源手机操作系统。它包括操作系统、用户界面和应用程序——…...
用户登录请求100w/每天, JVM如何调优
用户登录请求100w/每天, JVM如何调优 大概可以分为以下8个步骤。 Step1:新系统上线如何规划容量? 1.套路总结 任何新的业务系统在上线以前都需要去估算服务器配置和JVM的内存参数,这个容量与资源规划并不仅仅是系统架构师的随意估算的&am…...
C/C++每日一练(20230306)
目录 1. 判断素数的个数 ☆ 2. 分隔链表 ★★ 3. 数据流的中位数 ★★ 1. 判断素数的个数 在一个数组A中存放100个数据,用子函数判断该数组中哪些是素数,并统计该素数的个数,在主函数中输出该素数的个数。 代码: #includ…...
多线程的创建、Thread类、线程安全、同步、通信
目录 多线程的创建 方式一:继承Thread类 方式二:实现Runnable接口 方式三:JDK 5.0新增:实现Callable接口 Thread的常用方法 线程安全 线程安全问题是什么、发生的原因 线程安全问题案例模拟 线程同步 同步思想概述 方式…...
GraphPad Prism v9.5.1.733 科研绘图软件多语言
GraphPad Prism集生物统计、曲线拟合和科技绘图于一体,其所具有的功能均非常实用和精炼,包括了一些特色的功能,如ROC曲线分析、Bland-Altman分析等;曲线拟合功能是GraphPad Prism8 汉化版超越其他统计软体的制胜法宝,GraphPad Prism8 汉化版的线性/非线性拟合功能使用操作…...
基于intel soc+fpga智能驾驶舱和高级驾驶辅助系统软件设计(三)
虚拟化操作系统介绍 车载平台有逐渐融合的趋势,车载 SoC 的计算性能和应用快速增长,面临着多种应用在 多个显示子系统融合在一起的问题,这就要求平台运行多个操作系统。虚拟化(Virtualization) 技术飞速发展࿰…...
什么?年终奖多发1块钱竟要多缴9.6W的税
对于大多数的工薪阶级来说,目前现行的个人所得税适用于全年累计收入一次性税收优惠。 有可能有的人不理解一次性税收优惠是什么意思,所以这里我首先解释下什么是一次性税收优惠,然后在讲一下为什么明明公司多发了钱,到手反而会更…...
动态绑定右键菜单控件
一、动态绑定右键菜单控件 /// <summary> /// 通过递归获取执行控件 /// </summary> /// <typeparam name"T"></typeparam> /// <param name"c"></param> /// <pa…...
JavaScript基础三、数据类型
零、文章目录 文章地址 个人博客-CSDN地址:https://blog.csdn.net/liyou123456789个人博客-GiteePages:https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee:https://gitee.com/bluecusliyou/TechLearnGithub:https:…...
Python 随机漫步
目录 1. 创建 RandomWalk 类 2. 选择方向 3. 绘制随机漫步图 4. 总结 本篇博客将使用 Python 来 生成随机漫步数据,再使用 Matplotlib 库,将以引人注目的方式将这些数据呈现出来。 随机漫步 顾名思义就是随机走出的步伐,它是这样行…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
