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

article/2025/8/25 0:37:33

1. 概述

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

工厂模式(Factory Pattern)是 3 种工厂模式的总称 —— 简单工厂模式(Simple Factory)工厂方法模式(Factory Method)抽象工厂模式(Abstract Factory)

这 3 种模式从上到下逐步抽象,并且具有一般性。用一下案例来理解工厂模式:

(1)在没有工厂的时代,如果用户需要一款宝马车,那么就需要用户自己去创建一款宝马车,即用户自己去执行创建一款宝马车所需要的一系列的复杂的操作,然后才能拿来用;
(2)简单工厂模式:后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,即由工厂来执行创建宝马车的一些列复杂的操作,用户不用关心复杂的创建过程,用户想要什么车,直接通过工厂创建就可以了。比如,想要320i系列车,工厂就创建这个系列的车;
(3)工厂方法模式:为了满足不同用户的需求,宝马车推出了越来越多的车系以满足不同用户的需求,如320i系列、523i等等系列。原先一个工厂无法创建所有的宝马车系,于是又单独分出来多个具体的工厂,每个工厂创建一种车系,即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象,用户需要指定某个具体的工厂才能生产出他所需要的车。例如,客户需要宝马320i系列的车,那么他就需要执行生产宝马320i系列车的工厂生产一辆他所需要的车;
(4)抽象工厂模式:随着客户要求越来越高,宝马车必须配置空调,于是这个工厂开始生产宝马车和所需要的空调。用户只要提出他需要宝马320i空调车,宝马工厂就直接给他提供宝马320i空调车,而不用自己去创建宝马320i空调宝马车。

 

2. 简单工厂模式

简单工厂模式的核心是定义一个创建对象的接口,讲对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。

如果不使用工厂,用户将需要自己创建宝马车。

public class BMW320 {public BMW320() {System.out.println("制造-->BMW320");}
}public class BMW523 {public BMW523() {System.out.println("制造-->BMW523");}
}public class Customer {public static void main(String[] args) {// 不适用简单工厂模式时,用户需要宝马车,则需要自己去创建BMW320 bmw320 = new BMW320();BMW523 bmw523 = new BMW523();}
}

用户需要知道怎么创建一款车,这样客户和车就紧密耦合在一起了,为了降低耦合性,就出现了简单工厂模式,把创建宝马车的操作细节都放到了工厂里,而客户直接使用工厂的创建方法,传入想要的宝马车型号就行了,而不必去知道创建的细节。

UML类图

  • 工厂类角色:该模式的核心,用来创建产品,含有一定的商业逻辑和判断逻辑
  • 抽象产品角色:它一般是具体产品集成的父类或者实现的接口
  • 具体产品角色:工厂类所创建的对象就是次角色的实例,在JAVA中由一个具体的类实现

代码实现

产品类

public abstract class BMW {protected String type;public BMW() {}abstract public String getBMWType();
}public class BMW320 extends BMW {public BMW320() {System.out.println("制造-->BMW320");type = "BMW320";}@Overridepublic String getBMWType() {return type;}
}public class BMW523 extends BMW {public BMW523() {System.out.println("制造-->BMW523");type = "BMW523";}@Overridepublic String getBMWType() {return type;}
}

工厂类

public class BMWFactory {public BMW createBMW(String type) {switch (type) {case "320":return new BMW320();case "523":return new BMW523();default:break;}return null;}
}

Customer类

public class Customer {public static void main(String[] args) {BMWFactory bmwFactory = new BMWFactory();BMW bmw = bmwFactory.createBMW("320");System.out.println("BMW type: " + bmw.getBMWType());}
}

测试

 

简单工厂模式优缺点

优点
简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需要知道具体产品类所对应的参数即可。通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点
缺点在于不符合设计模式的 “开闭原则”(对扩展开放,对修改关闭),每次添加新的产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要收到影响。

为了解决简单工厂模式的问题,出现了工厂方法模式。

 

3. 工厂方法模式

UML图

  • 抽象工厂 AbstractFactory:工厂方法模式的核心,是具体工厂角色必须实现的接口或者必须继承的父类,在JAVA中它由接口或者抽象类来实现;
  • 具体工厂 Factory:被应用程序调用以创建具体产品的对象,含有和具体业务逻辑有关的代码;
  • 抽象产品 AbstractProduct:是具体产品类继承的父类或实现的接口,在JAVA中一般由抽象类或者接口来实现;
  • 具体产品 Product:具体工厂角色所创建的对象就是此角色的实例。
     

代码实现

产品类

public abstract class BMW {protected String type;public BMW() {}abstract public String getBMWType();
}public class BMW320 extends BMW {public BMW320() {System.out.println("制造-->BMW320");type = "BMW320";}@Overridepublic String getBMWType() {return type;}
}public class BMW523 extends BMW {public BMW523() {System.out.println("制造-->BMW523");type = "BMW523";}@Overridepublic String getBMWType() {return type;}
}

工厂类

public interface BMWFactory {BMW createBMW();
}public class BMW320Factory implements BMWFactory  {@Overridepublic BMW createBMW() {System.out.println("BMW320 工厂生产 BMW320");return new BMW320();}
}public class BMW523Factory implements BMWFactory  {@Overridepublic BMW createBMW() {System.out.println("BMW523 工厂生产 BMW523");return new BMW523();}
}

Consumer类

public class Consumer {public static void main(String[] args) {// 用户指定具体的生产工厂BMWFactory bmwFactory= new BMW523Factory();// 由指定的工厂生产产品BMW bmw = bmwFactory.createBMW();System.out.println("BMW type: " + bmw.getBMWType());}
}

测试

 

工厂方法模式的优缺点

 

4. 抽象工厂模式

在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体的工厂对应一个具体产品。但我们有时希望一个工厂能够提供多个产品对象,而不是单一的产品对象,这个时候就需要抽象工厂模式。

在了解抽象工厂模式之前,需要先理清楚 产品等级结构产品族 两个概念:

  • 产品等级结构
    产品等级结构指的是产品的继承结构,例如一个空调抽象类,它有海尔空调、隔离空调、美的空调等一系列的子类,那么这个空调抽象类和它的子类就构成了一个产品等级结构;

  • 产品族
    产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。例如,海尔工厂生产海尔空调、海尔冰箱,那么海尔空调、海尔冰箱就位于海尔产品族中。

抽象工厂主要用于创建相关对象的家族,当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用一个产品族中的对象;并且通过隔离具体类的生产,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

但该模式的缺点在于添加新的行为时比较麻烦,如果需要添加一个新的产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。

 

UML图

  • 抽象工厂 AbstractFactory:定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口;
  • 具体工厂 ConcreteFactory:用于生产不同的产品族,要创建一个产品,用户只需使用其中一个工厂进行获取,完全不需要实例化任何产品对象;
  • 抽象产品 AbstractProduct:这是一个产品家族,每一个具体工厂都能够生产一整组产品;
  • 具体产品 Product

 

代码实现

通过抽象工厂模式,我们可以实现以下的效果:比如宝马320系列使用空调型号A和发动机型号A,而宝马523系列使用空调型号B和发动机型号B,在为320系列生产相关配件时,就无需指定配件的型号,它会自动根据车型生产对应的配件型号A。

也就是说,当每个抽象产品都有多余一个具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?抽象工厂模式提供两个具体工厂角色(宝马320系列工厂和宝马523系列工厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化,每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。

产品类

// Engine
public abstract class AbstractEngine {/*** 引擎的型号*/protected String type;abstract public String getType();
}public class EngineA extends AbstractEngine {public EngineA() {this.type = "Engine A";}@Overridepublic String getType() {return this.type;}
}public class EngineB extends AbstractEngine {public EngineB() {this.type = "Engine B";}@Overridepublic String getType() {return this.type;}
}// AirConditioner
public abstract class AbstractAirConditioner {/*** 空调的型号*/protected String type;abstract public String getType();
}public class AirConditionerA extends AbstractAirConditioner {public AirConditionerA() {this.type = "AirConditioner A";}@Overridepublic String getType() {return this.type;}
}public class AirConditionerB extends AbstractAirConditioner {public AirConditionerB() {this.type = "AirConditioner B";}@Overridepublic String getType() {return this.type;}
}

工厂类

public interface BMWFactory {AbstractEngine createEngine();AbstractAirConditioner createAirConditioner();
}public class BMW320Factory implements BMWFactory {@Overridepublic AbstractEngine createEngine() {System.out.println("制造 Engine A");return new EngineA();}@Overridepublic AbstractAirConditioner createAirConditioner() {System.out.println("制造 AirConditioner A");return new AirConditionerA();}
}public class BMW523Factory implements BMWFactory {@Overridepublic AbstractEngine createEngine() {System.out.println("制造 Engine B");return new EngineB();}@Overridepublic AbstractAirConditioner createAirConditioner() {System.out.println("制造 AirConditioner B");return new AirConditionerB();}
}

Consumer类

public class Consumer {public static void main(String[] args) {BMWFactory bmwFactory = new BMW523Factory();AbstractEngine engine = bmwFactory.createEngine();AbstractAirConditioner airConditioner = bmwFactory.createAirConditioner();System.out.println("Engine型号: " + engine.getType());System.out.println("AirConditioner型号: " + airConditioner.getType());}
}

测试

 

5. 工厂模式小结

工厂方法模式与抽象工厂模式的区别在于:

1)工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例;

2)抽象工厂模式拥有多个产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例。

 

参考文献

[1] https://blog.csdn.net/a745233700/article/details/120253639?spm=1001.2014.3001.5506


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

相关文章

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

设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,如果设计模式没学会,抽象能力肯定就不会太强。常见的设计模式有 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 前提:在一张图里,不能有权值为负数的边。 给你一个出发点,求出发点到所有结点的最短距离是多少?如果无法到达某个点,则到这个点的距离是正无穷(一般出现在有向图里面)。 举个&#…

最短路径算法详解

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

基于java最短路径算法的简单实现

一、我们先画一个可达路径图表: -1表示不可直达,0表示自己,其他整数表示长度或者权重 ABCDA012-1B-1015C-1-101D-1-1-10 用图形可表示为: 二、算法思路 1、先列出所有保存所有节点到可达节点的路径二维表 2、逐步寻找从起始节点到…

最短路径算法及应用

乘汽车旅行的人总希望找出到目的地的尽可能的短的行程。如果有一张地图并在图上标出每对十字路口之间的距离,如何找出这一最短行程?  一种可能的方法就是枚举出所有路径,并计算出每条路径的长度,然后选择最短的一条。那么我们很…

关于最短路径算法的理解

“最短路径算法:Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法等。​从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径叫做最短路径。” 我们解决最短路径问题,常用的是Dijkstra…

最短路径算法-----Dijkstra迪杰斯特拉算法

最近巩固一下算法,提高自己内力,网上看到查看到这篇介绍很详细的《Dijkstra迪杰斯特拉算法》,在这里转载记录一下。 1 前言 本章介绍迪杰斯特拉算法。和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给…

Dijkstra 最短路径算法 Python 实现

原文链接 问题描述 使用 Dijkstra 算法求图中的任意顶点到其它顶点的最短路径(求出需要经过那些点以及最短距离)。 以下图为例: 算法思想 可以使用二维数组来存储顶点之间边的关系 首先需要用一个一维数组 dis 来存储 初始顶点到其余各个顶…

神经网络最短路径算法,最短路径算法的原理

节约里程法求解最短路问题 你只要记住2点之间直线最短。节约里程法是用来解决运输车辆数目不确定的问题的最有名的启发式算法。1、节约里程法优化过程分为并行方式和串行方式两种。 核心思想是依次将运输问题中的两个回路合并为一个回路,每次使合并后的总运输距离…

最短路径算法及Python实现

最短路径问题 在图论中,最短路径问题是指在一个有向或无向的加权图中找到从一个起点到一个终点的最短路径。这个问题是计算机科学中的一个经典问题,也是许多实际问题的基础,例如路线规划、通信网络设计和交通流量优化等。在这个问题中&#…

图论:图的四种最短路径算法

目录: 1.DFS(单源最短路径算法) 例题1: DFS题目分析: 代码DFS: 2.Floyed(时间复杂度On^3) 1.应用场景: 2.解析算法: 核心代码1: 我的笔…