三大工厂模式

创建型模式

  • 创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则
  • 创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。

简单工厂模式

模式定义

  • 简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
  • 在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式结构

简单工厂模式结构

  1. Factory:工厂角色
    工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法 factoryMethod(),它的返回类型为抽象产品类型 Product
  2. Product:抽象产品角色
    它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。
  3. ConcreteProduct:具体产品角色
    它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。

模式实例

简单工厂模式实例

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
// 抽象产品类 TV(电视机类)
public interface TV {
public void play();
}

// 具体产品类 HaierTV(海尔电视机类)
public class HaierTV implements TV {
@Override
public void play() {
System.out.println("海尔电视机播放中……");
}
}

// 具体产品类 HisenseTV(海信电视机类)
public class HisenseTV implements TV {
@Override
public void play() {
System.out.println("海尔电视机播放中……");
}
}

// 工厂类 TVFactory(电视机工厂类)
public class TVFactory {
public static TV productTV(String brand) throws Exception{
if(brand.equalsIgnoreCase("Haier")){
System.out.println("电视机工厂生产海尔电视机!");
return new HaierTV();
}else if(brand.equalsIgnoreCase("Hisense")){
System.out.println("电视机工厂生产海信电视机!");
return new HisenseTV();
}else
throw new Exception("对不起,暂不能生产该品牌电视机!");
}
}

// 客户端测试类 Client
public class Client {
public static void main(String[] args) {
try {
TV tv;
String brandName = "Haier";
tv = TVFactory.productTV(brandName);
tv.play();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

模式优缺点

简单工厂模式的优点

  • 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象
  • 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
  • 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

简单工厂模式的缺点

  • 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
  • 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
  • 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构
  • 简单工厂模式最大的缺点是当有新产品要加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这违背了“开闭原则”

工厂方法模式

模式定义

  • 工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
  • 在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

模式结构与分析

工厂方法模式结构

  • Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
  • ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
  • Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
  • ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体产品对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好地符合了“开闭原则”。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

模式实例

工厂方法模式实例

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
// 抽象产品类 TV(电视机类)
public interface TV {
public void play();
}

// 具体产品类 HaierTV(海尔电视机类)
public class HaierTV implements TV {
@Override
public void play() {
System.out.println("海尔电视机播放中……");
}
}

// 具体产品类 HisenseTV(海信电视机类)
public class HisenseTV implements TV {
@Override
public void play() {
System.out.println("海尔电视机播放中……");
}
}

// 抽象工厂类 TVFactory(电视机工厂类)
public interface TVFactory {
public TV produceTV();
}

// 具体工厂类 HaierTVFactory(海尔电视机工厂类)
public class HaierTVFactory implements TVFactory {
@Override
public TV produceTV() {
System.out.println("海尔电视机工厂生产海尔电视机!");
return new HaierTV();
}
}

// 具体工厂类 HisenseTVFactory(海信电视机工厂类)
public class HisenseTVFactory implements TVFactory {
@Override
public TV produceTV() {
System.out.println("海信电视机工厂生产海信电视机!");
return new HisenseTV();
}
}

// 客户端测试类 Client
public class Client {
public static void main(String[] args) {
try {
TV tv;
TVFactory factory;
factory = new HaierTVFactory();
tv = factory.produceTV();
tv.play();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

模式优缺点

工厂方法模式的优点

  • 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  • 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

工厂方法模式的缺点

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

抽象工厂模式

模式定义

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式

模式结构与分析

抽象工厂模式结构

  • AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
  • AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
  • ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构

模式实例

抽象工厂模式实例

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
// 抽象产品类 Television(电视机类)
public interface Television {
public void play();
}

// 具体产品类 HaierTelevision(海尔电视机类)
public class HaierTelevision implements Television {
@Override
public void play() {
System.out.println("海尔电视机播放中……");
}
}

// 具体产品类 TCLTelevision(TCL电视机类)
public class TCLTelevision implements Television {
@Override
public void play() {
System.out.println("TCL电视机播放中……");
}
}

// 抽象产品类 AirConditioner(空调类)
public interface AirConditioner {
public void changeTemperature();
}

// 具体产品类 HaierAirConditioner(海尔空调类)
public class HaierAirConditioner implements AirConditioner {
@Override
public void changeTemperature() {
System.out.println("海尔空调温度改变中……");
}
}

// 具体产品类 TCLAirConditioner(TCL空调类)
public class TCLAirConditioner implements AirConditioner {
@Override
public void changeTemperature() {
System.out.println("TCL空调温度改变中……");
}
}

// 抽象工厂类 EFactory(电器工厂类)
public interface EFactory {
public Television produceTelevision();
public AirConditioner produceAirConditioner();
}

// 具体工厂类 HaierFactory(海尔工厂类)
public class HaierFactory implements EFactory {
@Override
public Television produceTelevision() {
return new HaierTelevision();
}
@Override
public AirConditioner produceAirConditioner() {
return new HaierAirConditioner();
}
}

// 具体工厂类 TCLFactory(TCL工厂类)
public class TCLFactory implements EFactory {
@Override
public Television produceTelevision() {
return new TCLTelevision();
}
@Override
public AirConditioner produceAirConditioner() {
return new TCLAirConditioner();
}
}

// 客户端测试类 Client
public class Client {
public static void main(String[] args) {
try {
EFactory factory;
Television tv;
AirConditioner ac;
factory = new HaierFactory();
tv = factory.produceTelevision();
tv.play();
ac = factory.produceAirConditioner();
ac.changeTemperature();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

模式优缺点

抽象工厂模式的优点

  • 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
  • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
  • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

抽象工厂模式的缺点

  • 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
  • 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)

拓展

“开闭原则”的倾斜性

  • “开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
  1. 增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。
  2. 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。
  • 抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。

工厂模式的退化

当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

文章目录
  1. 1. 创建型模式
  2. 2. 简单工厂模式
    1. 2.1. 模式定义
    2. 2.2. 模式结构
    3. 2.3. 模式实例
    4. 2.4. 模式优缺点
      1. 2.4.1. 简单工厂模式的优点
      2. 2.4.2. 简单工厂模式的缺点
  3. 3. 工厂方法模式
    1. 3.1. 模式定义
    2. 3.2. 模式结构与分析
    3. 3.3. 模式实例
    4. 3.4. 模式优缺点
      1. 3.4.1. 工厂方法模式的优点
      2. 3.4.2. 工厂方法模式的缺点
  4. 4. 抽象工厂模式
    1. 4.1. 模式定义
    2. 4.2. 模式结构与分析
    3. 4.3. 模式实例
    4. 4.4. 模式优缺点
      1. 4.4.1. 抽象工厂模式的优点
      2. 4.4.2. 抽象工厂模式的缺点
  5. 5. 拓展
    1. 5.1. “开闭原则”的倾斜性
    2. 5.2. 工厂模式的退化

20160528-DesignPattern-3/

本页二维码