Earth Guardian

You are not LATE!You are not EARLY!

0%

设计模式--创建型:简单工厂、工厂方法模式、抽象工厂模式

工厂模式有三种:简单工厂,工厂方法模式,抽象工厂模式。

简单工厂 Simple Factory

简单工厂模式,又称为静态工厂模式(Static Factory Method),并不属于 23 种 GOF 设计模式之一。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

类图结构

0049-SimpleFactory-uml-classdiag.png

结构解析

  • Factory
    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • Product
    抽象类,简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  • Concrete Product
    是简单工厂模式的创建目标,具体实现类。

示例

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
// 1. Product
public abstract class Product {
public abstract void function();
}

// 2. ConcreteProduct
public class ProductA extends Product{

@Override
public void function() {
System.out.println("Product A can fly.");
}
}

public class ProductB extends Product {

@Override
public void function() {
System.out.println("Product B can run.");
}
}

// 3. Factory
public class ProductFactory {
public static final int SPEC_FLY = 1;
public static final int SPEC_RUN = 2;

public static Product createProduct(int spec){
Product product = null;
switch (spec) {
case SPEC_FLY:
product = new ProductA();
break;
case SPEC_RUN:
default:
product = new ProductB();
break;
}
return product;
}
}

// 4. Test
public class TestSimpleFactory {
public static void main(String[] args) {
Product product=ProductFactory.createProduct(ProductFactory.SPEC_FLY);
product.function();

product = ProductFactory.createProduct(ProductFactory.SPEC_RUN);
product.function();
}
}

// 5. Result
Product A can fly.
Product B can run.

小结

由于工厂类集中了所有实例的创建逻辑,违反了开闭原则。将全部创建逻辑集中到了一个工厂类中,它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,对系统的维护和扩展非常不利,这些缺点在工厂方法模式中得到了一定的克服。
因此工厂类一般在很简单情况下使用:负责创建的对象比较少,客户只需要知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。

工厂方法模式 Factory Method

工厂方法模式 Factory Method定义一个用于创建对象的接口,让子类决定实现哪一个类。工厂方法使一个类的实例化延迟到其子类。

类图结构

0049-FactoryMethod-uml-classdiag.png

结构解析

  • Product
    抽象类,定义工厂方法创建的对象。
  • ConcreteProduct
    实现类,具体的产品。
  • Creator
    抽象类,产品创建抽象类。必须包含工厂方法,该方法是抽象方法,并且返回抽象产品。
    public abstract Product factoryMethod();
  • ConcreteCreator
    实现类,实现工厂方法,创建具体的产品。

示例

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
// 1. Product
public abstract class Product {
public abstract void method();
}

// 2. ConcreteProduct
public class ProductA extends Product{
@Override
public void method() {
System.out.println("Product A is sweet.");
}
}

public class ProductB extends Product{
@Override
public void method() {
System.out.println("Product B is salty.");
}
}

// 3. Creator
public abstract class Creator {
public abstract Product factoryMethod();
}

// 4. ConcreteCreator
public class ProductACreator extends Creator {
@Override
public Product factoryMethod() {
return new ProductA();
}
}

public class ProductBCreator extends Creator {
@Override
public Product factoryMethod() {
return new ProductB();
}
}

// 5. Test
public class TestFactoryMethod {
public static void main(String[] args) {
Creator productACreator = new ProductACreator();
Product productA = productACreator.factoryMethod();
productA.method();

Creator productBCreator = new ProductBCreator();
Product productB = productBCreator.factoryMethod();
productB.method();
}
}

// 6. Result
Product A is sweet.
Product B is salty.

小结

工厂方法模式中的 FactoryMethod 的特点:抽象,new 一个新产品并返回。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现开闭原则,实现了可扩展;缺点是会增加很多类,加大了代码量。

抽象工厂模式 Abstract Factory

抽象工厂模式 Abstract Factory提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类

类图结构

0049-AbstractFactory-uml-classdiag.png

结构解析

  • AbstractProduct
    抽象类,抽象产品。表示某一类型产品,比如 CPU 系列,内存系列等。
  • ConcreteProduct
    实现类,具体的产品,比如具体的 AMD 或者 Intel 型号的 CPU;大小为 2G/4G 的内存。
  • AbstractFactory
    抽象类,抽象工厂,表示组装一个产品集合时,必须生产哪些产品类型。比如必须生产 CPU 以及内存。
  • ConcreteFactory
    实现类,工厂的具体实现。明确该工厂生产具体的产品,比如生产 AMD CPU 和大小为 2G 的内存。

示例

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
// 1. AbstractProduct
public abstract class AbstractProductA {
public abstract String toString();
}

public abstract class AbstractProductB {
public abstract String toString();
}

// 2. AbstractFactory
public abstract class AbstractFactory {
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}

// 3. ConcreteProduct
public class ConcreteProductA1 extends AbstractProductA{
@Override
public String toString() {
return "AMD CPU ";
}
}

public class ConcreteProductA2 extends AbstractProductA{
@Override
public String toString() {
return "Intel CPU ";
}
}

public class ConcreteProductB1 extends AbstractProductB{
@Override
public String toString() {
return "2G RAM ";
}
}

public class ConcreteProductB2 extends AbstractProductB{
@Override
public String toString() {
return "4G RAM";
}
}

// 4. ConcreteFactory
public class ConcreteFactory1 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}

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

public class ConcreteFactory2 extends AbstractFactory{
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}

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

// 5. Test
public class TestAbstractFactory {
public static void main(String[] args) {
AbstractFactory abstractFactory1 = new ConcreteFactory1();
AbstractProductA abstractProductA1 =abstractFactory1.createProductA();
AbstractProductB abstractProductB1 =abstractFactory1.createProductB();
System.out.println("Computer config: " +
abstractProductA1.toString() + abstractProductB1.toString());

AbstractFactory abstractFactory2 = new ConcreteFactory2();
AbstractProductA abstractProductA2 =abstractFactory2.createProductA();
AbstractProductB abstractProductB2 =abstractFactory2.createProductB();
System.out.println("Computer config: " +
abstractProductA2.toString() + abstractProductB2.toString());
}
}

// 6. Result
Computer config: AMD CPU 2G RAM
Computer config: Intel CPU 4G RAM

小结

抽象工厂模式主要用来创建产品集合,比如组装一台电脑,一辆车,他们通常由固定数量的零部件组成,但是每个零部件都会有多种配置。每一个具体的工厂,都会产生具体配置的产品集合,如果需要生产其他不同配置,只需要添加一个类继承抽象工厂就行,符合开闭原则。而且客户端只需要依赖抽象产品类,并不需要关心具体产品,符合依赖倒转原则
抽象工厂模式的缺点也很明显:一是会导致增加很多相关类,二是如果工厂的流水线并不固定,增加了一个抽象产品类,则需要添加产品实现类,并且修改抽象工厂类,以及所有的工厂实现类。

总结

  • 简单工厂
    用来生产同一等级结构中的任意产品。不支持增加产品,违反开闭原则。
  • 工厂方法
    用来生产同一等级结构中的固定产品。支持增加产品,只需增加对应的工厂实现类。
  • 抽象工厂
    用来生产不同配置的产品族。支持增加产品族,只需增加具体的工厂实现类,配置不同的产品类型。但是不支持增加产品,会修改抽象工厂及所有工厂实现类。

参考文档