Java设计模式之抽象工厂模式

  工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。在Java设计模式之工厂方法模式中我们讲述了工厂模式中的简单工厂模式和工厂方法模式,在这篇文章中我们将剩下的一个工厂模式——抽象工厂模式。   

产品等级结构和产品族

  为了更好地理解抽象工厂模式,我们先引入两个概念:
  (1) 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  (2) 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
  
  产品等级结构和产品族的示意图如下:
  
  image_1b24rmo191dhsc8fo4kis51qtn9.png-40.3kB
  
  在上图中,不同颜色的多个正方形、圆形和椭圆形分别构成了三个不同的产品等级结构,而相同颜色的正方形、圆形和椭圆形构成了一个产品族,每一个形状对象都位于某个产品族,并属于某个产品等级结构。图3中一共有五个产品族,分属于三个不同的产品等级结构。我们只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一确定这个产品。      

抽象工厂模式

  当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。
  
  抽象工厂方法模式UML图如下:
  
  image_1b23geh7hqj0rim2ho1kja1bm89.png-128.8kB
  
  在工厂方法模式中,一个工厂只生产一个产品等级结构的产品,例如在工厂方法模式中讲到的,一个工厂只生产宝马车这一种产品等级结构的产品(不管是BMW320,还是BMW523,都属于同一产品等级结构,即宝马车)。现在设想这样一种情况,既要生产汽车引擎,又要生产汽车方向盘,而且既有宝马品牌的引擎和方向盘,又有奔驰品牌的引擎和方向盘,那么现在就出现了两种产品等级结构,引擎和方向盘,其中宝马品牌的引擎和宝马品牌的方向盘构成一个产品族,奔驰品牌的引擎和奔驰品牌的方向盘构成一个产品族,UML类图如下:
  
  image_1b23ie1jdsoc1epajgv119tih2m.png-56.9kB
  
  当使用工厂方法模式,你可以替换生成引擎的工厂方法,就可以把引擎从宝马换到奔驰。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换引擎和方向盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便。所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线,因为工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
  
代码如下:

引擎类:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IEngine {}
public class BMWEngine implements IEngine {
public BMWEngine() {
System.out.println("BMWEngine has been created!");
}
}
public class BenzEngine implements IEngine {
public BenzEngine() {
System.out.println("BenzEngine has been created!");
}
}

方向盘类:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IWheel {}
public class BMWWheel implements IWheel {
public BMWWheel() {
System.out.println("BMWWheel has been created!");
}
}
public class BenzWheel implements IWheel {
public BenzWheel() {
System.out.println("BenzWheel has been created!");
}
}

工厂类:

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
public interface IFactory {
public IEngine creatEngine();
public IWheel creatWheel();
}
public class BMWFactory implements IFactory {
@Override
public IEngine creatEngine() {
return new BMWEngine();
}
@Override
public IWheel creatWheel() {
return new BMWWheel();
}
}
public class BenzFactory implements IFactory {
@Override
public IEngine creatEngine() {
return new BenzEngine();
}
@Override
public IWheel creatWheel() {
return new BenzWheel();
}
}

客户端测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {
public static void main(String[] args) {
IFactory bmwFactory = new BMWFactory();
IEngine bmwEngine = bmwFactory.creatEngine();
IWheel bmwWheel = bmwFactory.creatWheel();
IFactory benzFactory = new BenzFactory();
IEngine benzEngine = benzFactory.creatEngine();
IWheel benzWheel = benzFactory.creatWheel();
}
}

运行结果:

image_1b23jsfph1ghrr4j8ucu1f7r13.png-15kB

总结:

工厂方法模式:
  一个抽象产品类,可以派生出多个具体产品类。
  一个抽象工厂类,可以派生出多个具体工厂类。
  每个具体工厂类只能创建一个具体产品类的实例。
  
抽象工厂模式:
  多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
  一个抽象工厂类,可以派生出多个具体工厂类。
  每个具体工厂类可以创建多个具体产品类的实例。