Java 设计模式 - 工厂

Java 是一门面向对象的语言,一般情况下,我们要获取一个对象的实例,需要用 new 关键字来创建,而在多数情况下,创建一个实例还需要一些初始设置等其他操作,就是一个过程而不是一个简单的操作。比如有一个客户想要一个小动物,传统的做法就是:

Client

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
    Animal cat = new Cat();
Animal dog = new Dog();
```

![](https://s.niuhp.com/blog/pattern/factory/common.png)

这样做的问题是客户需要知道怎么去创建一个小动物,客户和动物就紧密耦合在了一起,为了解决这个问题,于是就有了工厂模式,工厂模式可以简单分为三类:

1. 简单工厂
2. 工厂方法
3. 抽象工厂

#### 1 简单工厂

简单解决客户和动物耦合的问题很简单,我们只需要在两者之间引入一个工厂类,负责创建动物实例,而客户只需要向工厂要实例就行了。

**[AnimalFactory](https://github.com/niuhp/basic-java/blob/master/src/main/java/com/niuhp/basic/pattern/factory/simple/AnimalFactory.java)**

``` java
public class AnimalFactory {
public Animal createAnimal(String type) {
switch (type) {
case "cat":
return new Cat();
case "dog":
return new Dog();
default:
return null;
}
}
}
```

**[Client](https://github.com/niuhp/basic-java/blob/master/src/test/java/com/niuhp/basic/pattern/factory/simple/AnimalFactoryTest.java)**

``` java
AnimalFactory af = new AnimalFactory();
Animal cat = af.createAnimal("cat");
Animal dog = af.createAnimal("dog");

简单工厂主要包含3个角色:

  1. 抽象动物(Animal),一般为具体产品继承的父类或者实现的接口
  2. 具体动物(CatDog),工厂类所创造的对象
  3. 工厂类(AnimalFactory),模式的核心,负责创建具体产品的实例,有一定的处理逻辑

这种模式虽然解决了客户和动物的耦合问题,但是每增加一个动物,我们不得不在工厂类中新增一个 case ,需要修改以前的代码,这显然不能达到我们的要求,于是我们对这种模式进行扩展,有了工厂方法模式。

2 工厂方法

这种模式为每个动物创建一个工厂,当有新动物增加时,我们只需要为新动物增加一个工厂类即可,不需要修改以前代码,主要包含 4 个角色:

  1. 抽象动物(Animal),一般为具体产品继承的父类或者实现的接口
  2. 具体动物(CatDog),工厂类所创造的对象
  3. 抽象工厂(AnimalFactory),一般为具体工厂的父类或者接口
  4. 具体工厂(CatFactoryDogFactory),具体的工厂,负责具体动物的创建

AnimalFactory

public interface AnimalFactory {
  Animal createAnimal();
}

CatFactory

public class CatFactory implements AnimalFactory {
  @Override
  public Animal createAnimal() {
    return new Cat();
  }
}

DogFactory

public class DogFactory implements AnimalFactory {
  @Override
  public Animal createAnimal() {
    return new Dog();
  }
}

Client

    AnimalFactory cf = new CatFactory();
    Animal cat = cf.createAnimal();
    AnimalFactory df = new DogFactory();
    Animal dog = df.createAnimal();

3 抽象工厂

抽象工厂是将一组具有相同主题的封装起来,使用的时候,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

如图所示,我们假定猫和狗都有男女之分,(CatFactory可以创建男猫和女猫,DogFactory可以创建男狗和女狗,客户端通过具体工厂实现来创建相应实例。

CatFactory

public class CatFactory implements AnimalFactory {

  @Override
  public Animal createMale() {
    return new Cat("male");
  }

  @Override
  public Animal createFemale() {
    return new Cat("female");
  }
}

DogFactory

public class DogFactory implements AnimalFactory {
  @Override
  public Animal createMale() {
    return new Dog("male");
  }

  @Override
  public Animal createFemale() {
    return new Dog("female");
  }
}

Client

    AnimalFactory cf = new CatFactory();
    Animal maleCat = cf.createMale();
    Animal femaleCat = cf.createFemale();
    AnimalFactory df = new DogFactory();
    Animal maleDog = df.createMale();
    Animal femaleDog = df.createFemale();

4 其他