抽象工厂模式

背景

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题。 但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类, 势必会增加系统的开销。

假设你正在开发一款家具商店模拟器。

  1. 你的代码中包括一些类,用于表示一系列相关产品.

    • 例如椅子Chair、沙发Sofa和咖啡桌Coffee­Table

  2. 系列产品的不同变体。

    • 例如,你可以使用现代Modern、维多利亚Victorian、装饰风艺术Art­Deco等 风格生成椅子、沙发和咖啡桌 。

product-theme

如果使用工厂方法模式,存在以下问题:

  • 需要为每个产品都提供一个产品工厂类,这样类的个数成对增加,这无疑会导致系统越来越庞大, 从而增加了系统的维护成本和运行开销。

  • 由于同一种风格的具体界面组件通常要一起显示,因此需要为每个组件都选择一个具体工厂, 用户在使用时必须逐个进行设置。如果某个具体工厂选择失误将会导致界面显示混乱, 虽然可以适当增加一些约束语句,但客户端代码和配置文件都较为复杂。

此时,可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产。

定义

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

工厂方法模式可以看作是解决创建某一类产品的解决方法,当需要创建多种风格的多种产品时,为避免 创建过多的类,就可以使用抽象工厂模式。比如下面这些场景:

  • 支持多种主题的按钮、列表、输入框等

  • 支持多种风格的沙发、椅子、餐桌等

抽象工厂模式

实现

沙发、椅子是抽象产品类型,Modern、Art 是不同的产品主题,也就是不同的工厂类。

抽象工厂模式例子

评价

优点

  • 增加新的产品族很方便,无须修改已有系统,符合开闭原则

  • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象

缺点

  • 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码, 这显然会带来较大的不便,比如新增一个家具床,就需要在抽象工厂中新增加一个创建床的方法, 并且所有工厂子类都需要去实现这个方法,这违背了开闭原则。