当前位置: 首页 > 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;它是这样行…...

Spark SQL优化机制

Spark SQL优化机制Spark SQLCatalyst 优化器逻辑优化物理优化TungstenUnsafe RowWSCGRDD 缺点 : RDD的算子都是高阶函数 &#xff0c;Spark Core 不知函数内的操作&#xff0c;只能闭包形式发给 Executors&#xff0c; 无法优化 DataFrame 不同点&#xff1a; 数据的表示形式…...

十五、Spring中的八大模式

1 简单工厂模式 BeanFactory的getBean()方法&#xff0c;通过唯一标识来获取Bean对象。是典型的简单工厂模式&#xff08;静态工厂模式&#xff09;&#xff1b; 2 工厂方法模式 FactoryBean是典型的工厂方法模式。在配置文件中通过factory-method属性来指定工厂方法&#x…...

GrabCut算法、物体显著性检测

图割GraphCus算法。利用颜色、纹理等信息对GraphCut进行改进&#xff0c;形成效果更好的GrabCut算法。 对图像的目标物体和背景建立一个K维的全协方差高斯混合模型。 其中&#xff0c;单高斯模型的概率密度函数用公式表示为&#xff1a; 高斯混合模型可表示为n个单高斯模型的概…...

亚马逊、速卖通、lazada店铺一直不出单,没流量怎么办?

近几年&#xff0c;跨境电商入驻的卖家越来越多&#xff0c;平台的流量越来越分散&#xff0c;导致店铺没有流量没有订单的情况经常发生&#xff0c;因此卖家对店铺的优化尤为主要。 对于亚马逊卖家来说&#xff0c;几乎每天都会问虽然我把我的产品放在货架上&#xff0c;但没…...

深度剖析C语言符号篇

致前行的人&#xff1a; 人生像攀登一座山&#xff0c;而找寻出路&#xff0c;却是一种学习的过程&#xff0c;我们应当在这过程中&#xff0c;学习稳定冷静&#xff0c;学习如何从慌乱中找到生机。 目录 1.注释符号&#xff1a; 2.续接符和转义符&#xff1a; 3.回车与换行…...

【学习总结】ORBSLAM3使用自己相机数据

本文仅用于自己学习总结。本文档记录如何修改ORBSLAM3的接口&#xff0c;用自己的图片和数据。 单目视觉&#xff0c;无IMU&#xff0c;离线数据运行的配置过程 euroc_examples.sh 首先从euroc_examples.sh这个运行指令改。这个文件在最新版的代码中被删掉了&#xff0c;但通…...

C++单例模式实现

目录 1.提出的需求 ​​​​​​​2.如何定义一个类&#xff0c;使得这个类最多只能创建一个对象&#xff1f; ​​​​​​​3.代码 ​​​​​​​4.小结 C/CLinux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 ​​​​​​​1.提出的需求 在架构设计时&am…...

343. 整数拆分

343. 整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。示例 2: 输入: n 10 输出: 36…...

SCAFFOLD: Stochastic Controlled Averaging for Federated Learning学习

SCAFFOLD: Stochastic Controlled Averaging for Federated Learning学习背景贡献论文思想算法局部更新方式全局更新方式实验总结背景 传统的联邦学习在数据异构(non-iid)的场景中很容易产生“客户漂移”(client-drift )的现象&#xff0c;这会导致系统的收敛不稳定或者缓慢。…...

第十四届蓝桥杯三月真题刷题训练——第 3 天

目录 题目1&#xff1a;门牌制作 题目描述 运行限制 代码&#xff1a; 题目2&#xff1a;货物摆放_long 题目描述 答案提交 运行限制 代码&#xff1a; 题目3&#xff1a;跳跃_dp 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码&#xff1a; 题目4&a…...