设计模式-抽象工厂

抽象工厂(Abstract Factory)

wiki

抽象工厂模式提供了一种方式来封装一组独立的工厂有一个共同的主题,而无需指定它们具体的类。在正常情况下,客户端软件创建抽象工厂的具体实现,然后使用工厂的通用接口创建作为主题一部分的具体对象。该客户端不知道,他从这些内部工厂获得哪些具体的对象,因为它仅使用其产品的通用接口。该模式将一组对象的实现细节与一般方法分开,并依赖于对像组合,因为对象创建是在工厂类暴露的方法中实现的。

概述

Abstract Factory 设计模式是23种著名的GoF设计模式之一,它描述了如何解决重复出现的设计问题,以灵活且可重用的面向对象软件,即易于实现的对象,更改,测试和重用。

抽象工厂设计模式解决如下问题:

  • 应用程序如何独立于其对象的创建方式?
  • 一个类如何独立于它创建的对象的方式?
  • 如何创建相关或依赖对象的关系?

直接在需要对象的类中创建对象是不灵活的,因为它将类交给特定的对象,并且无法在以后独立于类来更改实例。如果需要其他对象,它会阻止该类可重用,并且难以测试,应为实际对象不能模拟对象替换。

抽象工厂设计模式描述了如何解决这些问题:

  • 将对象创建封装在单独的(工厂)对象中。也就是说,定义一个用于创建对象的接口,并且实现接口。
  • 类将对象创建委托给工厂对象,而不是直接创建对象。

这使得一个类独立于其对象的创建方式。一个类可配置一个工厂对象,用它来创建对象,甚至可以在运行时交换工厂对象。

定义

提供一个接口,用于创建相关或从属的一类对象,而不指定它们的具体类。

实例

接口

Castle.java

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 城堡
* @author luokai
*/
public interface Castle {
/**
* 获得描述
* @return 描述
*/
String getDescription();

}

King.java

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 国王
* @author luokai
*/
public interface King {

/**
* 获得描述
* @return 描述
*/
String getDescription();
}

Army.java

1
2
3
4
5
6
7
8
9
10
11
/**
* 军队
* @author luokai
*/
public interface Army {
/**
* 获得描述
* @return 描述
*/
String getDescription();
}

KingdomFactory.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 国家创建工厂
* @author luokai
*/
public interface KingdomFactory {

/**
* 创建城堡
* @return
*/
Castle createCastle();

/**
* 创建国王
* @return
*/
King createKing();

/**
* 创建军队
* @return
*/
Army createArmy();
}

精灵族

ElfCastle.java

1
2
3
4
5
6
7
8
9
10
/**
* 精灵族城堡
* @author luokai
*/
public class ElfCastle implements Castle {
@Override
public String getDescription() {
return "精灵族城堡";
}
}

ElfKing.java

1
2
3
4
5
6
7
8
9
10
/**
* 精灵族国王
* @author luokai
*/
public class ElfKing implements King {
@Override
public String getDescription() {
return "精灵族国王";
}
}

ElfArmy.java

1
2
3
4
5
6
7
8
9
10
/**
* 精灵族军队
* @author luokai
*/
public class ElfArmy implements Army {
@Override
public String getDescription() {
return "精灵族军队";
}
}

ElfKingdomFactory.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 精灵族国家创建工厂
* @author luokai
*/
public class ElfKingdomFactory implements KingdomFactory {
@Override
public Castle createCastle() {
return new ElfCastle();
}

@Override
public King createKing() {
return new ElfKing();
}

@Override
public Army createArmy() {
return new ElfArmy();
}
}

兽族

OrcCastle.java

1
2
3
4
5
6
7
8
9
10
/**
* 兽族城堡
* @author luokai
*/
public class OrcCastle implements Castle {
@Override
public String getDescription() {
return "兽族城堡";
}
}

OrcKing.java

1
2
3
4
5
6
7
8
9
10
/**
* 兽族国王
* @author luokai
*/
public class OrcKing implements King {
@Override
public String getDescription() {
return "兽族国王";
}
}

OrcArmy.java

1
2
3
4
5
6
7
8
9
10
/**
* 兽族军队
* @author luokai
*/
public class OrcArmy implements Army {
@Override
public String getDescription() {
return "兽族军队";
}
}

OrcKingdomFactory.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 兽族国家创建工厂
* @author luokai
*/
public class OrcKingdomFactory implements KingdomFactory {
@Override
public Castle createCastle() {
return new OrcCastle();
}

@Override
public King createKing() {
return new OrcKing();
}

@Override
public Army createArmy() {
return new OrcArmy();
}
}

APP

App.java

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
public class App {

private King king;
private Castle castle;
private Army army;

public King getKing() {
return king;
}

public void setKing(King king) {
this.king = king;
}

public Castle getCastle() {
return castle;
}

public void setCastle(Castle castle) {
this.castle = castle;
}

public Army getArmy() {
return army;
}

public void setArmy(Army army) {
this.army = army;
}

public void createKingdom(final KingdomFactory factory) {
setKing(factory.createKing());
setCastle(factory.createCastle());
setArmy(factory.createArmy());
}

public static void main(String[] args) {
App app = new App();
app.createKingdom(makeFactory(KingdomType.ELF));
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());

app.createKingdom(makeFactory(KingdomType.ORC));
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
}

public enum KingdomType {
ELF, ORC
}

public static KingdomFactory makeFactory(KingdomType kingdomType) {
switch (kingdomType) {
case ELF:
return new ElfKingdomFactory();
case ORC:
return new OrcKingdomFactory();
default:
throw new IllegalArgumentException("错误的 KingdomType");
}
}
}