通过前篇文章《设计模式:工厂模式,解除耦合的利器》的介绍,我们对工厂模式有了深入的了解,今天继续介绍一种特殊的工厂模式,也就是抽象工厂模式。
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式,是工厂方法模式的升级版,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
抽象工厂模式包含了几个角色:
AbstractFactory:用于声明生成抽象产品的方法
ConcreteFactory:实现了抽象工厂声明的生成抽象产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中;
AbstractProduct:为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法;
Product:定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法。
这是它的通用类图:
其中 AbstractProductA 和 AbstractProductB 就是两个产品族的抽象类 (或者接口),而 Product1 和 Product2 就是产品族下的具体产品类,AbstractCreator 就是工厂的抽象。
我们可以用操作系统来举例,现在市面上用的最多的两种PC端操作系统是windows和Linux,两个系统都有共同类型的组件,如文件夹,按钮,文本等。套用下抽象工厂的通用类图,我们不难发现,两个系统就相当于产品组抽象类AbstractProductA 和 AbstractProductB,而按钮、文本这些组件就是具体的产品类。
然后再来分析一下,如果有一个应用要在两个系统上运行,应该怎么设计?是编写两套程序运行于不同的系统上?这样实在是太浪费资源了,我们可以通过抽象工厂模式屏蔽掉操作系统对应用的影响。软件功能、逻辑、UI 都一个非常类似,唯一的不同是调用不同的工厂方法,由不同的产品类去处理与操作系统交互的信息,而这就是抽象工厂的优势。
抽象工厂的通用类图我们已经了解了,下面就是具体代码的实现:
产品族的抽象类,AbstractProductA 和 AbstractProductB,
public abstract class AbstractProductA { //每个产品共有的方法 public void shareMethod() { } // 每个产品相同方法,不同实现 public abstract void doSomething(); }
public abstract class AbstractProductB { //每个产品共有的方法 public void shareMethod() { } // 每个产品相同方法,不同实现 public abstract void doSomething(); }
两个产品族的具体实现类代码,
public class ProductA1 extends AbstractProductA { public void doSomething() { System.out.println("我是产品A1"); } }
public class ProductA2 extends AbstractProductA { public void doSomething() { System.out.println("我是产品A2"); } }
public class ProductB1 extends AbstractProductB { public void doSomething() { System.out.println("我是产品B1"); } } public class ProductB2 extends AbstractProductB { public void doSomething() { System.out.println("我是产品B2"); } }
抽象工厂类AbstractCreator
,有N个产品族,在抽象工厂类中就应该有N个创建方法。我们这里定义两个产品族的产品创建,代码如下:
public abstract class AbstractCreator { //创建A产品 public abstract AbstractProductA createProductA(); //创建B产品 public abstract AbstractProductB createProductB(); }
然后是创建产品的具体工厂,有N个产品等级就应该有N个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
public class Creator1 extends AbstractCreator { public AbstractProductA createProductA() { return new ProductA1(); } public AbstractProductB createProductB() { return new ProductB1(); } } public class Creator2 extends AbstractCreator { public AbstractProductA createProductA() { return new ProductA2(); } public AbstractProductB createProductB() { return new ProductB2(); } }
到此为止,我们把所有的角色都创建出来了,最后设计一个场景类,验证下是否能输出对应产品的信息,
public class Client { public static void main(String[] args) { //定义出两个工厂 AbstractCreator creator1 = new Creator1(); AbstractCreator creator2 = new Creator2(); //产生A1对象 AbstractProductA a1 = creator1.createProductA(); //产生A2对象 AbstractProductA a2 = creator2.createProductA(); //产生B1对象 AbstractProductB b1 = creator1.createProductB(); //产生B2对象 AbstractProductB b2 = creator2.createProductB(); a1.doSomething(); a2.doSomething(); b1.doSomething(); b2.doSomething(); } }
运行的结果为:
我是产品A1 我是产品A2 我是产品B1 我是产品B2
总结下抽象工厂模式的特点,抽象工厂是所有形式的工厂模式中最为抽象和最具一般性的一种形态,其优缺点大致如下:
1、隔离了具体类的生成,使得客户并不需要知道什么被创建,具有良好的封装性。
2、横向扩展容易。同个产品族如果需要增加多个 产品,只需要增加新的工厂类和产品类即可。
3、纵向扩展困难。如果增加新的产品组,抽象工厂类也要添加创建该产品组的对应方法,这样一来所有的具体工厂类都要做修改了,严重违背了开闭原则。
参考:
《设计模式之禅》