Java设计模式(四)抽象工厂模式

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)

本文及主要介绍抽象工厂模式。

抽象工厂模式

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

抽象工厂模式中,一个工厂可以提供多个不同种类产品对象,而不是单一种类的产品对象。

为了更清晰地理解工厂方法模式,需要先引入两个概念:

产品等级结构: 产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

产品族: 在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。

当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。

抽象工厂模式

抽象工厂模式包含角色和工厂方法模式相同。

假设有一个移动终端工厂,可以制造苹果系列的移动产品和华为系列的移动产品。
这个工厂下有两个子厂,一个负责制造苹果系列的 Pad 和华为系列的 Pad ,另一个负责制造苹果系列的手机和华为系列的手机。这便是一个典型的抽象工厂的实例。

1、创建产品产品接口

// 苹果系列
public interface Apple {
void AppleStyle();
}
// 华为系列
public interface Huawei {
void HuaweiStyle();
}

2、实现具体产品角色

// 苹果系列产品
public class iPhone implements Apple {
@Override
public void AppleStyle() {
System.out.println("Apple's style: iPhone!");
}
}
public class iPad implements Apple {
@Override
public void AppleStyle() {
System.out.println("Apple's style: iPad!");
}
}
// 华为系列产品
public class Honor implements Huawei {
@Override
public void HuaweiStyle() {
System.out.println("Huawei's style: Honor!");
}
}
public class HuaweiPad implements Huawei {
@Override
public void HuaweiStyle() {
System.out.println("Huawei's style: HuaweiPad!");
}
}

3、创建抽象工厂接口

public interface Factory {
Apple createAppleProduct();
Huawei createHuaweiProduct();
}

4、实现具体工厂类,生成实例对象,和工厂方法模式的核心区别

// 手机工厂
public class PhoneFactory implements Factory {
@Override
public Apple createAppleProduct() {
return new iPhone();
}
@Override
public Huawei createHuaweiProduct() {
return new Honor();
}

}
// 平板工厂
public class PadFactory implements Factory {
@Override
public Apple createAppleProduct() {
return new iPad();
}
@Override
public Huawei createHuaweiProduct() {
return new HuaweiPad();
}

}

5、调用不同工厂的方法生成实例对象

public class AbstractFactoryMain {
public static void main(String[] args) {

Factory factory = new PhoneFactory();
Apple apple = factory.createAppleProduct();
apple.AppleStyle();
Huawei huawei = factory.createHuaweiProduct();
huawei.HuaweiStyle();

factory = new PadFactory();
apple = factory.createAppleProduct();
apple.AppleStyle();
huawei = factory.createHuaweiProduct();
huawei.HuaweiStyle();

}
}

抽象工厂模式优缺点:

优点:
1、抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
2、增加新的具体工厂和产品族很方便,因为一个具体的工厂实现代表的是一个产品族,无须修改已有系统,符合“开闭原则”。

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

适用环境

1、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
2、系统中有多于一个的产品族,而每次只使用其中某一产品族。与工厂方法模式的区别
3、属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
4、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

本文实现源码https://github.com/wshunli/design-patterns/tree/master/src/ch04

参考资料
1、java中的工厂模式 - 简书
https://www.jianshu.com/p/bf8341c75304
2、《JAVA与模式》之抽象工厂模式 - java_my_life - 博客园
https://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html