抽象工厂模式

概述

《设计模式》中对抽象工厂(Abstract Factory) 模式的意图描述如下:

提供一个接口以创建一系列相关或相互依赖的对象,而无需指定它们具体的类

一般抽象工厂中的类结构如下图所示:

AbstractFactory.png

每个组件的介绍如下:

  • AbstractFactory:一个创建抽象产品对象的接口
  • ConcreateFactory:创建具体产品的实现类
  • AbstractProduct:对一类产品的统一抽象
  • ConcreateProduct:实际的产品对象
  • Client:用于访问 AbstractFactoryAbstractProduct 的客户端对象

具体示例

假设现在有一个需求,需要能够灵活地创建多种类型的风格 UI 组件(如菜单、滚动条等),首先我们需要定一个抽象接口,规定相关的创建行为:

public interface UIFactory {
    Menu createMenu(); // 创建 UI 的菜单栏组建
    ScrollBar createScrollBar(); // 创建对滚动条组建
    Window createWindow(); // 创建窗口组件
}

现在访问该 UI 工厂的对象 Client 是另一个与之相互隔离的对象,比如说一个文本编辑器对象,需要通过该 UI 工厂对象在自己的领域中添加对应的 UI 组件:

public class TextEditor {
    public TextEditor createTextEditor(UIFactory factory) {
        TextEditor editor = new TextEditor();
        editor.setMenu(factory.createMenu());
        editor.setScrollBar(factory.createScrollBar());
        editor.setWindow(factory.createWindow());
        return editor;
    }
}

现在,具体的文本编辑器的创建已经很好地处理了和 UI 组件之间的依赖关系,使得系统之间的耦合程度大大减小

如果现在需要使得文本编辑器的风格是暗色的,那么我们只需要定义一个实现了 UIFactory 的暗色工厂,将它传给 TextEditor 进行创建即可:

public class BlackUIFactory implements UIFactory {
    @Override
    public Menu createMenu() {return new BalckMenu();}
    
    @Override
    public ScrollBar createScrollBar() {return new BlackScrollBar();}
    
    @Override
    public Window createWindow() {return new BlackWindow();}
}

而随着时间的推移,可能会希望能够提供极简风格的组件,那么我们同样可以横向拓展丰富系统的功能:

public class SimpleUIFactory implements UIFactory {
    @Override
    public Menu createMenu() {return new SimpleMenu();}
    
    @Override
    public ScrollBar createScrollBar() {return new SimpleScrollBar();}
    
    @Override
    public Window createWindow() {return new SimpleWindow();}
}

当需要替换不同风格的组件时,只需要传入不同的 UIFactory 实例即可,而无需关心实际的实例内容

总结

抽象工厂模式存在以下的一些优点:

  • 抽象工厂分离了具体的类,客户端只需要知道抽象接口即可实现操作实例的逻辑,降低了系统的耦合程度
  • 使得产品系列的交换变得容易。从上面的示例中我们可以看到,当希望修改组件的风格时,只需要改变传入的具体工厂实例
  • 有利于产品的一致性。当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,而通过 AbstractFactory 则很容易实现这一点

当然,使用抽象工厂模式也存在一些不足,最大的不足之处便是不支持纵向扩展,即一个抽象工厂很难生产新的产品。这是因为 AbstractFactory 接口确定一个可以创建的产品集合,而如果需要生产新的产品的话,将会涉及到所有子类的改动


参考:

[1] 《设计模式—可复用面向对象基础》

posted @ 2022-10-29 19:24  FatalFlower  阅读(23)  评论(0编辑  收藏  举报