【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 库,将以引人注目的方式将这些数据呈现出来。 随机漫步 顾名思义就是随机走出的步伐,它是这样行…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
