1. 简单工厂模式

在了解工厂方法模式之前,有必要对“简单工厂”模式进行一定的了解,简单工厂模式是一种创建型设计模式,但并不属于23种设计模式之一,更多的是一种编程习惯。

简单工厂模式的核心思想是将产品的创建过程封装在一个工厂类中,把创建对象的流程集中在这个工厂类里面。

简单工厂模式包括三个主要角色,工厂类、抽象产品、具体产品,下面的图示则展示了工厂类的基本结构。

  • 抽象产品,比如下图中的Shape 接口,描述产品的通用行为。
  • 具体产品: 实现抽象产品接口或继承抽象产品类,比如上面的Circle类和Square类,具体产品通过简单工厂类的if-else逻辑来实例化。
  • 工厂类:负责创建产品,根据传递的不同参数创建不同的产品示例。

image-20240423225428549

简单工厂类简化了客户端操作,客户端可以调用工厂方法来获取具体产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新的产品,就需要修改工厂类的代码。

2. 什么是工厂方法模式

工厂方法模式也是一种创建型设计模式,简单工厂模式只有一个工厂类,负责创建所有产品,如果要添加新的产品,通常需要修改工厂类的代码。而工厂方法模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建一个具体产品,添加新的产品只需要添加新的工厂类而无需修改原来的代码,这样就使得产品的生产更加灵活,支持扩展,符合开闭原则。

工厂方法模式分为以下几个角色:

  • 抽象工厂:一个接口,包含一个抽象的工厂方法(用于创建产品对象)。
  • 具体工厂:实现抽象工厂接口,创建具体的产品。
  • 抽象产品:定义产品的接口。
  • 具体产品:实现抽象产品接口,是工厂创建的对象。

image-20240423230028070

实际上工厂方法模式也很好理解,就拿“手机Phone”这个产品举例,手机是一个抽象产品,小米手机、华为手机、苹果手机是具体的产品实现,而不同品牌的手机在各自的生产厂家生产。

3. 基本实现

根据上面的类图,我们可以写出工厂方法模式的基本实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 抽象产品
interface Shape {
void draw();
}

// 具体产品 - 圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle");
}
}

// 具体产品 - 正方形
class Square implements Shape {
@Override
public void draw() {
System.out.println("Square");
}
}

// 抽象工厂
interface ShapeFactory {
Shape createShape();
}

// 具体工厂 - 创建圆形
class CircleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}

// 具体工厂 - 创建正方形
class SquareFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Square();
}
}

// 客户端代码
public class Client {
public static void main(String[] args) {
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw(); // 输出:Circle

ShapeFactory squareFactory = new SquareFactory();
Shape square = squareFactory.createShape();
square.draw(); // 输出:Square
}
}

4. 应用场景

工厂方法模式使得每个工厂类的职责单一,每个工厂只负责创建一种产品,当创建对象涉及一系列复杂的初始化逻辑,而这些逻辑在不同的子类中可能有所不同时,可以使用工厂方法模式将这些初始化逻辑封装在子类的工厂中。在现有的工具、库中,工厂方法模式也有广泛的应用,比如:

  • Spring 框架中的 Bean 工厂:通过配置文件或注解,Spring 可以根据配置信息动态地创建和管理对象。
  • JDBC 中的 Connection 工厂:在 Java 数据库连接中,DriverManager 使用工厂方法模式来创建数据库连接。不同的数据库驱动(如 MySQL、PostgreSQL 等)都有对应的工厂来创建连接。

5. 举例说明

5.1 工厂方法模式-积木工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 抽象积木接口
interface Block {
void produce();
}

// 具体圆形积木实现
class CircleBlock implements Block {
@Override
public void produce() {
System.out.println("Circle Block");
}
}

// 具体方形积木实现
class SquareBlock implements Block {
@Override
public void produce() {
System.out.println("Square Block");
}
}

// 抽象积木工厂接口
interface BlockFactory {
Block createBlock();
}

// 具体圆形积木工厂实现
class CircleBlockFactory implements BlockFactory {
@Override
public Block createBlock() {
return new CircleBlock();
}
}

// 具体方形积木工厂实现
class SquareBlockFactory implements BlockFactory {
@Override
public Block createBlock() {
return new SquareBlock();
}
}

// 积木工厂系统
class BlockFactorySystem {
private List<Block> blocks = new ArrayList<>();

public void produceBlocks(BlockFactory factory, int quantity) {
for (int i = 0; i < quantity; i++) {
Block block = factory.createBlock();
blocks.add(block);
block.produce();
}
}

public List<Block> getBlocks() {
return blocks;
}
}

public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

// 创建积木工厂系统
BlockFactorySystem factorySystem = new BlockFactorySystem();

// 读取生产次数
int productionCount = scanner.nextInt();
scanner.nextLine();

// 读取每次生产的积木类型和数量
for (int i = 0; i < productionCount; i++) {
String[] productionInfo = scanner.nextLine().split(" ");
String blockType = productionInfo[0];
int quantity = Integer.parseInt(productionInfo[1]);

if (blockType.equals("Circle")) {
factorySystem.produceBlocks(new CircleBlockFactory(), quantity);
} else if (blockType.equals("Square")) {
factorySystem.produceBlocks(new SquareBlockFactory(), quantity);
}
}
}
}

本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.