当前位置: 首页 > news >正文

【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类是一个可变的字符串缓冲区&#xff0c…...

电路模型和电路定律(2)——“电路分析”

各位CSDN的uu们你们好呀,好久没有更新电路分析的文章啦,今天来小小复习一波,之前那篇博客,小雅兰更新了电路的历史以及电压电流的参考方向,这篇博客小雅兰继续!!! 电阻元件 电压源和…...

天琊超级进程监视器的应用试验(19)

实验目的 1、了解进程概念及其基本原理; 2、掌握天琊超级进程监视器的安装与使用。预备知识 本实验要求实验者具备如下的相关知识。 操作系统的安全配置是整个系统安全审计策略核心,其目的就是从系统根源构筑安全防护体系,通过用户的一…...

使用 Pulumi 打造自己的多云管理平台

前言在公有云技术与产品飞速发展的时代,业务对于其自身的可用性提出了越来越高的要求,当跨区域容灾已经无法满足业务需求的情况下,我们通常会考虑多云部署我们的业务平台,以规避更大规模的风险。但在多云平台部署的架构下&#xf…...

什么是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) 技术飞速发展&#xff0…...

什么?年终奖多发1块钱竟要多缴9.6W的税

对于大多数的工薪阶级来说,目前现行的个人所得税适用于全年累计收入一次性税收优惠。 有可能有的人不理解一次性税收优惠是什么意思,所以这里我首先解释下什么是一次性税收优惠,然后在讲一下为什么明明公司多发了钱,到手反而会更…...

动态绑定右键菜单控件

一、动态绑定右键菜单控件 /// <summary> /// 通过递归获取执行控件 /// </summary> /// <typeparam name"T"></typeparam> /// <param name"c"></param> /// <pa…...

JavaScript基础三、数据类型

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…...

Python 随机漫步

目录 1. 创建 RandomWalk 类 2. 选择方向 3. 绘制随机漫步图 4. 总结 本篇博客将使用 Python 来 生成随机漫步数据&#xff0c;再使用 Matplotlib 库&#xff0c;将以引人注目的方式将这些数据呈现出来。 随机漫步 顾名思义就是随机走出的步伐&#xff0c;它是这样行…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...