1. 什么是抽象工厂模式

抽象工厂模式也是一种创建型设计模式,提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

这样的描述似乎理解起来很困难,我们可以把它与【工厂方法模式】联系起来看。

之前我们已经介绍了“工厂方法模式”,那为什么还有要抽象工厂模式呢?

这就涉及到创建“多类”对象了,在工厂方法模式中,每个具体工厂只负责创建单一的产品。但是如果有多类产品呢,比如说“手机”,一个品牌的手机有高端机、中低端机之分,这些具体的产品都需要建立一个单独的工厂类,但是它们都是相互关联的,都共同属于同一个品牌,这就可以使用到【抽象工厂模式】。

抽象工厂模式可以确保一系列相关的产品被一起创建,这些产品能够相互配合使用,再举个例子,有一些家具,比如沙发、茶几、椅子,都具有古典风格的和现代风格的,抽象工厂模式可以将生产现代风格的家具放在一个工厂类中,将生产古典风格的家具放在另一个工厂类中,这样每个工厂类就可以生产一系列的家具。

2. 基本结构

抽象工厂模式包含多个抽象产品接口,多个具体产品类,一个抽象工厂接口和多个具体工厂,每个具体工厂负责创建一组相关的产品。

  • 抽象产品接口AbstractProduct: 定义产品的接口,可以定义多个抽象产品接口,比如说沙发、椅子、茶几都是抽象产品。
  • 具体产品类ConcreteProduct: 实现抽象产品接口,产品的具体实现,古典风格和沙发和现代风格的沙发都是具体产品。
  • 抽象工厂接口AbstractFactory: 声明一组用于创建产品的方法,每个方法对应一个产品。
  • 具体工厂类ConcreteFactory: 实现抽象工厂接口,负责创建一组具体产品的对象,在本例中,生产古典风格的工厂和生产现代风格的工厂都是具体实例。

image-20240423232726142

在上面的图示中:AbstractProductA/B/C 就是抽象产品,ConcreteProductA1/A2/B1/B2/C1/C2就是抽象产品的实现,AbstractFactory定义了抽象工厂接口,接口里的方法用于创建具体的产品,而ConcreteFactory就是具体工厂类,可以创建一组相关的产品。

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
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
89
90
91
92
93
94
// 1. 定义抽象产品
// 抽象产品A
interface ProductA {
void display();
}

// 抽象产品B
interface ProductB {
void show();
}

// 2. 实现具体产品类
// 具体产品A1
class ConcreteProductA1 implements ProductA {
@Override
public void display() {
System.out.println("Concrete Product A1");
}
}

// 具体产品A2
class ConcreteProductA2 implements ProductA {
@Override
public void display() {
System.out.println("Concrete Product A2");
}
}

// 具体产品B1
class ConcreteProductB1 implements ProductB {
@Override
public void show() {
System.out.println("Concrete Product B1");
}
}

// 具体产品B2
class ConcreteProductB2 implements ProductB {
@Override
public void show() {
System.out.println("Concrete Product B2");
}
}

// 3. 定义抽象工厂接口
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 4. 实现具体工厂类
// 具体工厂1,生产产品A1和B1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}

@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}

// 具体工厂2,生产产品A2和B2
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}

@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}

// 客户端代码
public class AbstractFactoryExample {
public static void main(String[] args) {
// 使用工厂1创建产品A1和产品B1
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.display();
productB1.show();

// 使用工厂2创建产品A2和产品B2
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.display();
productB2.show();
}
}

4. 应用场景

抽象工厂模式能够保证一系列相关的产品一起使用,并且在不修改客户端代码的情况下,可以方便地替换整个产品系列。但是当需要增加新的产品类时,除了要增加新的具体产品类,还需要修改抽象工厂接口及其所有的具体工厂类,扩展性相对较差。因此抽象工厂模式特别适用于一系列相关或相互依赖的产品被一起创建的情况,典型的应用场景是使用抽象工厂模式来创建与不同数据库的连接对象。

简单工厂、工厂方法、抽象工厂的区别

  • 简单工厂模式:一个工厂方法创建所有具体产品
  • 工厂方法模式:一个工厂方法创建一个具体产品
  • 抽象工厂模式:一个工厂方法可以创建一类具体产品

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.util.Scanner;

// 抽象椅子接口
interface Chair {
void showInfo();
}

// 具体现代风格椅子
class ModernChair implements Chair {
@Override
public void showInfo() {
System.out.println("modern chair");
}
}

// 具体古典风格椅子
class ClassicalChair implements Chair {
@Override
public void showInfo() {
System.out.println("classical chair");
}
}

// 抽象沙发接口
interface Sofa {
void displayInfo();
}

// 具体现代风格沙发
class ModernSofa implements Sofa {
@Override
public void displayInfo() {
System.out.println("modern sofa");
}
}

// 具体古典风格沙发
class ClassicalSofa implements Sofa {
@Override
public void displayInfo() {
System.out.println("classical sofa");
}
}

// 抽象家居工厂接口
interface FurnitureFactory {
Chair createChair();
Sofa createSofa();
}

// 具体现代风格家居工厂
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new ModernChair();
}

@Override
public Sofa createSofa() {
return new ModernSofa();
}
}

// 具体古典风格家居工厂
class ClassicalFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new ClassicalChair();
}

@Override
public Sofa createSofa() {
return new ClassicalSofa();
}
}

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

// 读取订单数量
int N = scanner.nextInt();

// 处理每个订单
for (int i = 0; i < N; i++) {
// 读取家具类型
String furnitureType = scanner.next();

// 创建相应风格的家居装饰品工厂
FurnitureFactory factory = null;
if (furnitureType.equals("modern")) {
factory = new ModernFurnitureFactory();
} else if (furnitureType.equals("classical")) {
factory = new ClassicalFurnitureFactory();
}

// 根据工厂生产椅子和沙发
Chair chair = factory.createChair();
Sofa sofa = factory.createSofa();

// 输出家具信息
chair.showInfo();
sofa.displayInfo();
}
}
}

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

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