抽象工厂模式
之前我们在学习工厂模式中,如果要增加一个产品,那么就会同时增加一个具体产品类和对应的具体工厂类,这会导致系统中的类数量成对的增加,加重系统的负担。而对于有些场景下我们使用的是一系列的类,这个时候我们就可以考虑将一些相关的产品组成一个产品“产品族”,然后由同一个工厂来统一生产。
在工厂模式中,每一个具体工厂都是针对一个具体产品的,工厂方法具有唯一性。那么为了更好的理解抽象工厂模式,先介绍两个概念:
- 产品等级结构。即产品的继承结构,如一个抽象类是电视机,那么子类就可以有海尔电视机、TCL电视机等,抽象电视机与具体电视机之前就构成了一个产品等级结构,抽象电视机是父类,而具体电视机是子类。
- 产品族。产品族指同一个工厂生产的,位于不同产品等级结构的一组产品。如海尔工厂生产海尔电视机、海尔电冰箱等。
产品等级结构与产品族示意图如下图所示:
抽象工厂模式是所有形式的工厂模式中最为抽象与最具有一般性的一种形式。抽象工厂模式与工厂方法模式的最大区别是:工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对的是多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更简单效率。
抽象工厂模式定义:提供一个创建一系列相关或者相互依赖对象的接口,而无须指定它们具有的类。抽象工厂模式又称为Kit模式,是一种对象创建型模式。
抽象工厂模式结构如图所示:
在上面的结构图中,包含以下几个角色:
- 抽象工厂
abstract class AbstractFactory {
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
- 具体工厂。具体工厂实现了抽象工厂,每一个具体的工厂方法都返回一个特定的产品对象,同一个工厂创建的产品构成一个产品族
class ConcreteFactory1 extends AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 extends AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
上面的代码中每一个具体工厂都包含两个工厂方法,分别生产产品A和B,而A1和B1、A2和B2分别构成了一个产品族。
那么客户端调用的时候就可以如下实现:
class Client {
public static void main(String args[]) {
AbstractFactory factory;
factory = new ConcreateFactory1();
ProductA = factory.createProductA();
ProductB = factory.createProductB();
}
}
在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,因为当增加新的产品等级结构的话,那么就需要修改抽象工厂的接口,之后针对每个具体工厂类修改实现。抽象工厂模式这种性质称为“开闭原则”的倾斜性。
总结:
所有的具体工厂都实现了抽象工厂定义的那些接口,当需要改变产品族的时候,只需要修改具体工厂的实例即可,无须知道什么产品被创建。另外使用抽象工厂模式也能够保证客户端始终只使用同一个产品族中的对象。
缺点: 当增加新的产品等级结构的时候,需要对原来系统中的抽象工厂,具体工厂都进行修改,违背了开闭原则。(开闭原则的倾斜性)
优点: 系统不应当关心产品类实例是如何被创建的细节,将对象的创建和使用解耦。确保同一个产品族中的产品将在一起使用。