Java工厂设计模式详解

article/2025/8/24 23:40:48

前言

工厂设计模式在开发过程中有大量的运用,不管是spring框架,还是诸多的中间件,都有着工厂设计模式的体现

比如,手机生产工厂,当提供了相关生产手机的原材料,工厂就可以按要求生产出手机

在这里插入图片描述

工厂模式介绍

工厂模式提供了一种创建对象的最佳方式,我们在创建对象的时候不会对客户端暴露具体的创建对象的逻辑,并通过使用一个共同创建的接口来指向新创建的对象

工厂模式常用实现方式

  • 简单工厂模式
    通过传入相关的类型参数来返回相应的类,这是最简单的一种实现方式,功能相对单一,ke扩展性较差

  • 工厂方法模式
    通过实现类实现相应的方法来决定相应的返回结果,这种方式的扩展性相对上面一种有较大提升

  • 抽象工厂模式
    基于上面两种方式的拓展,并且支持细化产品

工厂模式的应用场景及好处

  • 代码解耦
    职责分离,把复杂对象的创建和使用的过程分开
  • 代码复用,降低维护成本
    如果创建对象的过程比较复杂并且多处使用,假如每个使用的地方都需要重写一遍,将会产生很多重复代码,一旦业务逻辑发生变更,修改代码的地方就会很多,而使用工厂模式统一创建,只需要修改工厂类即可

下面通过代码实例演示下3种方式的实现过程

1、简单工厂模式

  1. 又称为静态工厂方法,可以根据参数的不同返回不同类的实例,需要专门定义一个类用于创建其他类的实例,被创建的类的实例通常具有共同的父类
  2. 由于工厂方法是静态方法,可以通过类名直接调用,而且只需要传入简单的参数即可

核心组成

  • Factory:工厂类,简单工厂模式的核心,负责实现创建所有实例的内部逻辑
  • IProduct:抽象产品类,简单工厂模式所创建的所有对象的父类,这里可理解为所有实例的公共接口或抽象类
  • ProductL具体产品类,简单工厂模式的创建目标

以一个实际的业务场景为例,某个业务需要对接各个主流的支付平台,假如需要后台支持支付宝,微信,银联3种甚至更多的支付方式,实际客户端调用的时候,希望做到根据传入某种支付类型就可以达到使用该支付方式支付的目的,这里尝试使用简单工厂模式进行实现

在这里插入图片描述

定义抽象产品支付接口Pay

/*** 抽象产品*/
public interface Pay {/*** 统一下单接口*/void unionPay();}

具体的产品类,这里包括3种,支付宝,微信,银联,即3种类型的具体的业务实现,这里叫做具体的产品类

支付宝,微信,银联

public class AliPay implements Pay {@Overridepublic void unionPay() {System.out.println("this is ali pay");}
}
public class WeChatPay implements Pay {@Overridepublic void unionPay() {System.out.println("this is wechat pay");}
}
public class BankPay implements Pay {@Overridepublic void unionPay() {System.out.println("this is bank pay");}
}

简单工厂,根据支付类型返回相应的支付实现

/*** 统一支付工厂类,根据传入的支付类型返回相应的支付方式*/
public class SimplePayFactory {public static Pay getPay(String type){switch (type){case "aliPay":return new AliPay();case "weChatPay":return new WeChatPay();case "bankPay":return new BankPay();default:return null;}}}

测试类:

public class Test {public static void main(String[] args) {Pay weChatPay = SimplePayFactory.getPay("weChatPay");weChatPay.unionPay();;}}

在这里插入图片描述

当尝试传入不同的type时,可以输出不同的结果,这就是简单工厂的实现,当然,具体在开发中,每种支付内部的业务是远远比上面的逻辑要复杂的

优点:

  • 将对象的创建和对象本身业务处理进行分离,一定程度上降低了系统的耦合性,这样一来当某种具体的支付产品发生变化时,修改起来相对简单

缺点:

  • 工厂职责相对单一,并且过重,新增加产品时需要修改工厂类的内部逻辑,这与开闭原则是相违背的
  • 当新增更多产品时,一定程度上会增加系统中类的个数,从而增加了系统的复杂度和理解难度,不利于系统的扩展和维护

2、工厂方法模式

  • 又称工厂模式,是对简单工厂的进一步抽象,好处是可以使得系统在不修改原来代码情况下引进新的产品,满足开闭原则
  • 通过工厂父类定义创建产品的公共接口,通过子类确定所需要创建的类型
  • 相比简单工厂,此模式具备更多的可扩扩展性和可复用性,同时也增强了代码的可读性
  • 将类的实例化(具体产品的创建)延迟到工厂类的子类完成,即由子类决定应该实例化哪一个类

用一张图简单解释下工厂方法模式下各个组件的位置

在这里插入图片描述

  • IProduct:抽象产品类,定义和描述所有产品的公共接口
  • Product:具体的产品类,比如这里的阿里支付,微信支付和银联支付
  • IFactory:抽象工厂类,描述具体实例工厂的公共接口
  • Factory:具体工厂,具体实现创建产品类对象的工厂,实际可能有多个

可以结合上图对工厂方法模式中的各个组件进行理解,下面结合具体的代码进行说明

复用简单工厂模式中的3种产品的代码,只需要定义右半边的部分代码即可

定义抽象产品工厂

public interface PayFactory {Pay getPay();
}

产出各个具体产品的工厂,比如对应这里aliPay,weChatPay,bankPay的3个工厂

public class AliPayFactory implements PayFactory {@Overridepublic Pay getPay() {return new AliPay();}
}
public class WechatPayFactory implements PayFactory {@Overridepublic Pay getPay() {return new WeChatPay();}
}
public class BankPayFactory implements PayFactory {@Overridepublic Pay getPay() {return new BankPay();}
}

测试类

public class FactoryTest {public static void main(String[] args) {PayFactory factory = new AliPayFactory();Pay pay = factory.getPay();pay.unionPay();}
}

在这里插入图片描述

可以通过new不同产品的工厂达到使用不同支付方式的目的

优点:

  • 增加一个产品类,只需要实现其他具体的产品类和具体的产品工厂类即可
  • 符合职责单一的原则,每个工厂只负责生产对应的产品
  • 使用者只需要知道产品的抽象接口即可,无须关心其他的实现类

缺点:

  • 增加一个产品,需要实现具体的产品类和具体的产品工厂
  • 每个产品都要有对应的工厂和具体的产品类

3、抽象工厂模式

  • 基于上述2种模式的拓展,属于工厂方法模式的升级版,当需要创建的产品存在多个产品线时可以考虑使用抽象工厂模式
  • 抽象工厂模式在spring框架中使用非常广泛

在上面的两种模式中,总结各自的优缺点,不难发现下面2点问题:

  • 工厂方法模式引入了工厂等级,解决了简单工厂模式中工厂类职责过重的问题
  • 但是工厂方法中每个工厂只针对某一个具体的产品,后续随着业务的拓展,可能导致工厂类过多,因此如果可以考虑将一些相关的具体类组成一个“类产品簇”,由同一个工厂统一生产,就可以减少工厂的创建,而抽象工厂模式正是基于这个思想,强调的是一系列相关产品的对象

何谓产品簇,可以理解为,手机厂商不仅可以代工安卓手机,还能代工苹果手机,甚至老人机等,这样一来,手机代工厂的职责相比只生产某种类型的手机就更强大了

在这里插入图片描述

按照上图所示的步骤,下面开始编写具体的代码进行实现

业务场景:在实际的订单场景中,涉及到两个操作,订单支付和支付对账,即createPay和checkPay,这两种业务,不管是支付宝还是微信,或者是其他支付平台,都可以进行操作

以此我们假定超级工厂(顶级父工厂)具备这两种业务能力,而对应的各个支付平台,它们也需要这两种业务产品的能力实现,按照上图,即支付宝和微信会有各自的业务对应的工厂,即AliOrderFactory 和WeChatOrderFactory,

1、定义超级工厂和业务工厂,持有各个业务的具体能力,这里理解为支付createPay和对账checkPay

/*** 支付对账*/
public interface CheckFactory {void checkPay();
}
/*** 支付工厂*/
public interface PayFactory {void createPay();
}
/*** 超级工厂*/
public interface OrderFactory {PayFactory createPay();CheckFactory createCheck();
}

2、定义支付宝自身的产品工厂和具体实现


/*** 支付宝对账产品实现*/
public class AliCheck implements CheckFactory {@Overridepublic void checkPay() {System.out.println("ali checkPay ,阿里支付对账");}
}
/*** 支付宝支付产品实现*/
public class AliPay implements PayFactory {@Overridepublic void createPay() {System.out.println("ali createPay ,阿里支付");}
}
/*** 支付宝工厂,对外输出的产品能力*/
public class AliOrderFactory implements OrderFactory {@Overridepublic PayFactory createPay() {return new AliPay();}@Overridepublic CheckFactory createCheck() {return new AliCheck();}}

3、定义微信自身的产品工厂和具体实现

public class WeChatCheck implements CheckFactory {@Overridepublic void checkPay() {System.out.println("wechat checkPay ,微信支付对账");}
}
public class WeChatPay implements PayFactory {@Overridepublic void createPay() {System.out.println("WeChatPay createPay ,微信支付");}
}
public class WeChatOrderFactory implements OrderFactory {@Overridepublic PayFactory createPay() {return new WeChatPay();}@Overridepublic CheckFactory createCheck() {return new WeChatCheck();}}

从上面的代码结构不难发现,在实际业务中,各个具体的支付平台都有自身的复杂的产品实现,比较好的方式就像上面的支付工厂,屏蔽掉底层的所有实现细节,客户都安只需要调用工厂找到相关的实现即可

4、提供一个工厂建造器,用于提供不同平台的支付工厂

/*** 工厂建造器*/
public class FactoryBuilder {public static OrderFactory getFactory(String type){switch (type){case "aliPay":return new AliOrderFactory();case "weChatPay":return new WeChatOrderFactory();default:return null;}}
}

最后提供一个简单的测试类

public class FactoryTest {public static void main(String[] args) {OrderFactory aliPay = FactoryBuilder.getFactory("aliPay");aliPay.createPay().createPay();}}

在这里插入图片描述

同时可以看到,抽象工厂设计模式从某种意义上,相当于是结合了前面两种模式的优点,可以说,抽象工厂模式并不是完全独立的一种模式

具体来说,优点:

  • 当一个产品簇中的多个对象被设计成一起工作时,它能保证使用的方法始终是同一个产品簇中的对象
  • 产品等级结构容易扩展,如果需要增加多更多的产品等级,只需要增加新的工厂类和产品类即可,比如增加银联支付等

缺点:

  • 产品簇扩展困难,要在某个系列中增加一个产品,需要同时在抽象工厂和抽象产品修改代码,不是很符合开闭原则
  • 增加了系统整体上的抽象性和理解上的难度,从代码的结构层次上可以发现这个问题

http://chatgpt.dhexx.cn/article/TEQVqbLM.shtml

相关文章

Android工厂设计模式(简单工厂,工厂方法,抽象工厂,BitmapFactory简单工厂分析,Retrofit抽象工厂分析)

文章目录 创建型设计模式(简单工厂,工厂方法,抽象工厂)一.简单工厂模式引出简单工厂模式 二.工厂方法模式三.抽象工厂模式 Android源码中用到的工厂模式举例一.BitmapFactory 源码工厂模式详解(简单工厂)二.Retrofit的工厂模式(抽象工厂) 创建型设计模式…

工厂设计模式有什么用?

工厂方法是非常古老且常用的设计模式。原因主要是一个系统要运转起来一定会涉及到对象的实例化过程,如果对象的实例化分散在各种逻辑代码之间,那么就会非常零乱、难以维护,bug自然也多。 工厂方法的出现解决的就是对象创建的问题&#xff0c…

Java中的工厂设计模式

引出工厂模式 package www.java.test;interface Computer{void printComputer(); } class MacbookPro implements Computer{Overridepublic void printComputer() {System.out.println("This is a MacbookPro");} } class SurfaceBook implements Computer{Override…

Java工厂设计模式

工厂设计模式 一、面向对象的设计原则1.1 OCP(开闭原则,Open-Closed Principle)1.2 DIP(依赖倒转原则,Dependence Inversion Principle)1.3 LOD(迪米特法则,Law Of Demeter&#xff…

设计模式—工厂设计模式

工厂设计模式 1.概述2.简单工厂模式2.1 结构2.2 实现2.3 优缺点2.4 扩展 3.工厂方法模式3.1 概述3.2 结构3.3 实现3.4 优缺点 4.抽象工厂模式4.1 概述4.2 结构4.3 实现4.4 优缺点4.5 应用场景 5.扩展模式5.1 第一步:定义配置文件5.2 改写工厂类 6.JDK源码解析—Coll…

工厂设计模式 - 详解

介绍 工厂模式是Java中最常用的设计模式之一,这种类型的设计模式数据创建型模式。 主要就是负责创建对象的,当我们使用new创建对象的时候会导致对该对象的耦合性很严重,当我们需要修改的时候需要对所有new的对象进行修改,违反了软…

【iOS】—— 工厂设计模式

工厂设计模式 文章目录 工厂设计模式设计模式概念设计模式七大准则开闭原则单⼀职责原则里氏替换原则依赖倒转原则接口隔离原则迪米特法则合成复用原则 类族模式简单工厂模式优点缺点主要作用示例文件分类实现效果: 工厂方法模式优点缺点主要作用:示例&a…

【设计模式】工厂模式(Factory Pattern)

1. 概述 工厂模式(Factory Pattern)是最常用的设计模式之一,它属于创建类型的设计模式。它提供了一种创建对象的最佳方式,在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过一个共同的接…

设计模式之工厂模式,史上最强,不服来辩!

设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,如果设计模式没学会,抽象能力肯定就不会太强。常见的设计模式有 23 种,今天我们只聊最简单的工厂模式。 工厂模式是属于创建型模式的,通过工厂获取一个一个的新对象。…

工厂设计模式

1、概念 工厂模式分三种:简单工厂模式、工厂方法模式、抽象工厂模式 简单工厂模式(Simple Factory Pattern):属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例&#xf…

设计模式之工厂模式(factory pattern)

工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。本文从一个具体的例子逐步深入分析,来体会三种工厂模式的应用场景和…

sqlserver2008的SSMS连接sqlserver2016的时候提示‘索引超出了数组界限。’

解决:打sp3补丁。 http://www.microsoft.com/en-us/download/details.aspx?id44271

Matlab报错 :“位置 x 处的索引超出数组边界”

经常遇到“位置 x 索引超出数组边界”的报错,今天突然想到一个以前一直没有太留意的奇葩问题:这个报错里“位置x”指的是哪里?为什么一会是“位置3”,一会是“位置1”,有什么神秘的规矩吗? 善用搜索没发现…

.net reflector 反编译失败 索引超出了数组界限问题处理方法

.net reflector 反编译失败 索引超出了数组界限问题处理方法 时间:9个月前 作者:庞顺龙 浏览:177 [站内原创,转载请注明出处] 标签: Reflector .net reflector 反编译失败 索引超出了数组界限问题处理方法 de…

matlab索引超出数组边界且不提示数组边界的一种处理办法

问题如下。 相关代码如下: 问题原因如下: 将excel表另存为txt时选择的保存类型是Unicode文本(*.txt)。 处理办法。 将Unicode文本(*.txt)换成文本文件(制表符分隔)(*.txt)。 问题的表现如下: 利用matlab工作区发现…

最短路径算法详细介绍

据 Drew 所知最短路经算法现在重要的应用有计算机网络路由算法,机器人探路,交通路线导航,人工智能,游戏设计等等。美国火星探测器核心的寻路算法就是采用的D*(D Star)算法。 最短路经计算分静态最短路计算和…

[算法]-最短路径算法总结

Dijkstra最短路径算法 按路径长度的递增次序,逐步产生最短路径的贪心算法 基本思想:首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v 到其它各顶点的最短路径全部求出为止。 时间复杂…

c++实现最短路径算法(Dijkstra算法)

0简介 Dijkstra算法是一种计算某一顶点到其余顶点最短路径的算法。它采用了贪心的策略,实现时使用了广度优先。这个算法常学常忘,因此写篇博客彻底解决它。 1计算步骤介绍 Dijkstra的计算步骤不难,如下 (1)设置一个集合表示已经标记过的节…

最短路径算法——dijkstra

dijkstra 前提:在一张图里,不能有权值为负数的边。 给你一个出发点,求出发点到所有结点的最短距离是多少?如果无法到达某个点,则到这个点的距离是正无穷(一般出现在有向图里面)。 举个&#…

最短路径算法详解

前言: 最短路径算法:用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 例子: 暑期,你想要出门去旅游,但是在你出发之前,你想知道任意…