抽象工厂模式
概述
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。它解决了工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,这就是抽象工厂模式的基本思想。
所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。
优点:
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然违背了开闭原则
什么情况下使用?
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 系统结构稳定,不会频繁的增加对象。
Demo示例
该Demo示例借鉴于JavaKeeper的文章工厂模式解读,该文章以清晰的脉络通俗易懂的诠释了抽象工厂模式,故在此记录。有兴趣的小伙伴可以点击上面的链接查看原文章。
假设我们要生产两种产品,键盘(Keyboard)和鼠标(Mouse) ,每一种产品都支持多种系列,比如 Mac 系列和 Windows 系列。这样每个系列的产品分别是 MacKeyboard、WinKeyboard、MacMouse、WinMouse 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族创建一个工厂 MacFactory 和 WinFactory 。每个工厂都有两个方法 CreateMouse 和 CreateKeyboard 并返回对应的产品,可以将这两个方法抽象成一个接口 AbstractFactory。具体关系如下图
-
首先我们新建一个抽象的工厂类AbstractFactory(既然是抽象工厂模式,我们就使用抽象类来定义)
/** * @Author Christy * @Date 2021/4/21 11:47 **/ public abstract class AbstractFactory { public abstract Keyboard createKeyboard(); public abstract Mouse createMouse(); }
-
定义具体产品类接口Keyboard、Mouse
/** * @Author Christy * @Date 2021/4/21 16:15 **/ public interface Keyboard { void input(); }
/** * @Author Christy * @Date 2021/4/21 16:15 **/ public interface Mouse { void click(); }
-
定义产品的具体实现类WindowsKeyboard、WindowsMouse、MacKeyboard、MacMouse
/** * @Author Christy * @Date 2021/4/21 16:36 **/ public class WindowsKeyboard implements Keyboard { @Override public void input() { System.out.println("Inside WindowsKeyboard::input() method!"); } }
/** * @Author Christy * @Date 2021/4/21 16:37 **/ public class WindowsMouse implements Mouse { @Override public void click() { System.out.println("Inside WindowsMouse::click() method!"); } }
/** * @Author Christy * @Date 2021/4/21 16:30 **/ public class MacKeyboard implements Keyboard { @Override public void input() { System.out.println("Inside MacKeyboard::input() method!"); } }
/** * @Author Christy * @Date 2021/4/21 16:35 **/ public class MacMouse implements Mouse { @Override public void click() { System.out.println("Inside MacMouse::input() method!"); } }
-
定义产品工厂类WindowsFactory、MacFactory继承自抽象工厂类
/** * @Author Christy * @Date 2021/4/21 11:48 **/ public class WindowsFactory extends AbstractFactory{ @Override public Keyboard createKeyboard() { return new WindowsKeyboard(); } @Override public Mouse createMouse() { return new WindowsMouse(); } }
/** * @Author Christy * @Date 2021/4/21 11:48 **/ public class MacFactory extends AbstractFactory { @Override public Keyboard createKeyboard() { return new MacKeyboard(); } @Override public Mouse createMouse() { return new MacMouse(); } }
-
编写Demo示例AbstractFactoryPatternDemo
/** * @Author Christy * @Date 2021/4/21 13:48 **/ public class AbstractFactoryPatternDemo { public static void main(String[] args) { /******************** 抽象工厂模式 ********************/ MacFactory macFactory = new MacFactory(); Keyboard macKeyboard = macFactory.createKeyboard(); macKeyboard.input(); Mouse macMouse = macFactory.createMouse(); macMouse.click(); WindowsFactory windowsFactory = new WindowsFactory(); Keyboard windowsKeyboard = windowsFactory.createKeyboard(); windowsKeyboard.input(); Mouse windowsMouse = windowsFactory.createMouse(); windowsMouse.click(); } }
-
测试结果
抽象工厂模式和工厂方法模式一样,都符合开闭原则。但是不同的是,工厂方法模式在增加一个具体产品的时候,都要增加对应的工厂。但是抽象工厂模式只有在新增一个类型的具体产品时才需要新增工厂。也就是说,工厂方法模式的一个工厂只能创建一个具体产品。而抽象工厂模式的一个工厂可以创建属于单一类型的多种具体产品。