【3W2H设计模式】抽象工厂模式(Abstract Factory Pattern)
一、WHAT 什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂;抽象工厂模式是创建型模式的一种,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
二、WHY 为什么用抽象工厂模式
采用工厂方法包括抽象工厂方法都有的一个好处是分离了创建对象的细节,封装了创建产品对象的过程,并且分析了具体的类,在客户端中通过接口进行调用,对产品创建和调用进行了解耦。其次抽象工厂方法是针对与一个产品族,使得易于交换产品系列,只需改变具体的工厂就可以使用不同的产品配置。
当一个产品族中的产品对象被设计成一起工作且一个应用只是用同一族的对象,抽象工厂的接口确定了可以被创建的产品集合。
三、WHEN 什么时候用抽象工厂模式
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
- 增加新的具体工厂和产品族很方便,因为一个具体的工厂实现代表的是一个产品族,无须修改已有系统,符合“开闭原则”。
- 抽象工厂模式主要在于应对“新系列”的需求变化。分离了具体的类,抽象工厂模式帮助你控制一个应用创建的对象的类,因为一个工厂封装创建产品对象的责任和过程。它将客户和类的实现分离,客户通过他们的抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。它使得易于交换产品系列。一个具体工厂类在一个应用中仅出现一次——即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。它有利于产品的一致性。当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。抽象工厂模式有助于这样的团队的分工,降低了模块间的耦合性,提高了团队开发效率。
四、HOW 如何实现抽象工厂模式
4.1 抽象工厂类图
4.2 抽象工厂组成及作用
编号 | 组成(角色) | 关系 | 作用 |
1 | 抽象产品族(AbstractProduct) | 抽象产品的父类 | 描述抽象产品的公共接口 |
2 | 抽象产品(Product) | 具体产品的父类 | 描述具体产品的公共接口 |
3 | 具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
4 | 抽象工厂(Creator) | 具体工厂的父类 | 描述具体工厂的公共接口 |
5 | 具体工厂(Concrete Creator) | 抽象工厂的子类;被外界调用 | 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例 |
4.3 抽象工厂实现的步骤
步骤1: 创建抽象产品族类 ,定义抽象产品的公共接口;
步骤2: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
步骤3: 创建抽象工厂类,定义具体工厂的公共接口;
步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
**步骤5:**客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
4.4 抽象工厂实例
步骤一:创建抽象产品族
/** * 创建抽象产品族A */ public abstract class ProductAAbstract { public void createToLine(String lineName) { System.out.println("This is ProductAAbstract Line"); } }
/** * 创建抽象产品族 ProductB */ public abstract class ProdutBAbstract { public void ProductionLine(String lineName) { System.out.println("This is ProductBAbstract LineName"); } }
步骤二: 实现抽象产品族并创建具体产品
/** * 创建具体产品ProductA */ public class ConcreteProductA extends ProductAAbstract { @Override public void createToLine(String lineName) { System.out.println("ConcreteProductA-"+lineName); } }
/** * 创建具体产品ProductAA */ public class ConcreteProductAA extends ConcreteProductA{ @Override public void createToLine(String lineName) { System.out.println("ConcreteProductAA-"+lineName); } }
/** * 继承ProdutBAbstract,创建具体产品ConcreteProductB */ public class ConcreteProductB extends ProdutBAbstract { @Override public void ProductionLine(String lineName) { System.out.println("ConcreteProductB-"+lineName); } }
/** * 实现ConcreteProductB,创建产品ConcreteProductBB */ public class ConcreteProductBB extends ConcreteProductB{ @Override public void ProductionLine(String lineName) { System.out.println("ConcreteProductBB-"+lineName); } }
步骤三: 创建抽象工厂
/** * 创建抽象工厂 */ public interface AbstractFactory { ProductAAbstract CreateAProductManage(); ProdutBAbstract CreateBProductManage(); }
步骤四:实现抽象工厂,并创建实例工厂
/** * 创建抽象工厂,并创建实例工厂ContreteFactoryA */ public class ContreteFactoryA implements AbstractFactory { @Override public ProductAAbstract CreateAProductManage() { return new ConcreteProductA(); } @Override public ProdutBAbstract CreateBProductManage() { return new ConcreteProductB(); } }
/** * 创建抽象工厂,并创建实例工厂ContreteFactoryB */ public class ContreteFactoryB implements AbstractFactory { @Override public ProductAAbstract CreateAProductManage() { return new ConcreteProductAA(); } @Override public ProdutBAbstract CreateBProductManage() { return new ConcreteProductBB(); } }
步骤五:客户端通过实例化具体的工厂类
/** * 客户端通过实例化具体的工厂类 */ public class Client { public static void main(String[] args) { Client client=new Client(); AbstractFactory factory= client.getFactory("A"); factory.CreateAProductManage().createToLine("LineName Factory"); factory.CreateBProductManage().ProductionLine("LineName Factory"); } public AbstractFactory getFactory(String FactoryName) { if ("A".equals(FactoryName)) { return new ContreteFactoryA(); } else if ("B".equals(FactoryName)) { return new ContreteFactoryB(); }else{ return null; } } }
五、HOW TO CHANGE(抽象工厂模式在代码中如何使用)
抽象工厂模式适用场景
- 忽略创建细节: 客户端不关心产品实例如何被创建 , 实现等细节;
- 创建产品族: 强调一系列相关的产品对象 , 一般是同一个产品族 , 一起使用 创建对象需要大量重复的代码 ;
- 产品类库: 提供一个产品类 的库 , 所有的产品 以 同样的接口出现 , 使 客户端不依赖于具体实现 ;