Abstract Factory (抽象工厂)模式
GoF : Abstract Factory 模 式的意图是“提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类”。
工厂模式有 : 抽象 工厂 (Abstract Factory) 、工厂方法 (Factory Method) 。依照《设计模式精解》的顺序,这里先学习 Abstract Factory 模式。
工厂模式是传说中用的最广的模式了。我们通常用某个类 Class 来生成一个对象,例如: A a = new A(); 所谓工厂就是生产某种产品的地方。那么工厂模式就是用来生成一些列产品(对象)的。有时候,几个对 象需要按照相同的样式被实例化。比如说,在处理显示器显示精度的时候,有些机器能显示高清晰图像,而有些机器只能显示低分辨率图像。那么在工作上就要求系 统去适配最合适的功能。 Abstract Factory 模式能确保系统总能根据当前的情况获得合 适的对象。
假如我们要开发一个系统,要求提供打印驱动和显示驱动,还要求在不同 配置的机器上要有合适的驱动,例如:在高配置的机器上要求精度高的驱动,在低配置的机器上要求精度低的驱动。
开始的解决方法这样:提供一个 DisplayDriver 抽象类(或者接口)然后派生出两个类 Lrdd (提 供低精度显示驱动)和 Hrdd (提供高精度显示驱动);再提供一个 PrintDriver 抽象类(或者接口)然后派生出两个类 Lrpd (提 供低精度打印驱动) Hrpd (提供高精度打印驱动)。最后在 ApControl 类中分别实例化四个派生类的对象来提供相关的驱动。这样做是很合理的,但是当需求改变了,现在要求提供中等精度的驱动,或者其它要求。我们又 从那两个抽象类中分别派生出若干子类。这样又出现了类爆炸的情况,我们要在 ApControl 类中分别实例化那些类才能提供我们所要的功能。这时我们就应该想一下用 Abstract Factory 模式了。先看一下 Abstract Factory 模式的 UML 图:
( )
Abstract Factory 模式 UML 图
在上图中我们可以看到,用一个工厂( ResFractory )来“生产”我们需要的“产品”(类)。我们不管有多少具体类,在 Abstract Factory 模式中 ApControl 类只使用 Abstract Factory 类( ResFactory 类)和 Abstract Product 类( DisplayDriver 类和 PrintDriver 类)的接口。通常在运行时刻创建一个具体类的实例。这一具体的工厂创建具有特定实现的产品对象。为 创建不同的产品对象,客户应使用不同的具体工厂。 Abstract Factory 将产品对 象的创建延迟到它的具体子类中。
下面给出上图 的简易代码:
先创建产品:
package Factory;
public abstract class DisplayDriver
{
public abstract void dDriver();// 抽 象方法,使派生类能够自由实现所需的显示功能。
}//end abstract class DisplayDriver
package Factory;
public class Lrdd extends DisplayDriver
{
public Lrdd()
{
System.out.println(" 低分辨率 __ 显示 驱动 ");
}//end Lrdd()
public void dDriver() // 实现基类抽象方法
{
System.out.println(" 显示出 __ 低分辨率图像 ");
}//end dDrover()
}//end class Lrdd
package Factory;
public class Hrdd extends DisplayDriver
{
public Hrdd()
{
System.out.println(" 高分辨率 -- 显示 驱动 ");
}//end Hrdd()
public void dDriver()
{
System.out.println(" 显示出 -- 高分辨率图像 ");
}//end dDriver()
}//end class Hrdd
package Factory;
public abstract class PrintDriver
{
public abstract void pDriver();// 抽 象方法,使派生类能够自由实现所需的打印功能。
}//end abstract class PrintDriver
package Factory;
public class Lrpd extends PrintDriver
{
public Lrpd()
{
System.out.println(" 低分辨率 __ 打印 驱动 ");
}//end Lrpd()
public void pDriver()
{
System.out.println(" 打印 __ 低分辨率图像 ");
}//end pDriver()
}//end class Lrpd
package Factory;
public class Hrpd extends PrintDriver
{
public Hrpd()
{
System.out.println(" 高分辨率 -- 打印 驱动 ");
}//end Hrpd()
public void pDriver()
{
System.out.println(" 打印 -- 高分辨率图像 ");
}//end pDriver()
}//end class Hrpd
再创建工厂:
package Factory;
public abstract class ResFactory
{
// 抽象方法,使派生类自由实现显示功能
abstract public DisplayDriver getDispDrvr();
// 抽象方法,使派生类自由实现打印功能
abstract public PrintDriver getPrtDrvr();
}//end abstract class ResFactory
package Factory;
public class LowResFact extends ResFactory {
public LowResFact()
{
System.out.println(" 低分辨率 ----> 驱动 ");
}//end LowResFact()
public DisplayDriver getDispDrvr()
{
return new Lrdd();
}//end getDispDrvr()
public PrintDriver getPrtDrvr()
{
return new Lrpd();
}//end getPrtDrvr()
}//end class LowResFact
package Factory;
public class HighResFact extends ResFactory
{
public HighResFact()
{
System.out.println(" 高分辨率 ----> 驱动 ");
}//end HighResFact()
public DisplayDriver getDispDrvr()
{
return new Hrdd();
}//end getDispDrvr()
public PrintDriver getPrtDrvr()
{
return new Hrpd();
}//end getPrtDrvr()
}//end class HighResFact
利用工厂产生不同的产品:
package Factory;
public class ApControl
{
private DisplayDriver lowDisplayDriver; // 需要 -- 低 -- 分辨率 -- 显示 -- 驱动
private PrintDriver highPrintDriver; // 需要 -- 高 -- 分辨率 -- 打印 -- 驱动
// 生产出低分 辨率驱动(注:没有说明是低显示驱动还是低打印驱动)
private ResFactory lowDriver;
// 生产出高分 辨率驱动(注:没有说明是高显示驱动还是高打印驱动)
private ResFactory highDriver;
public ApControl()
{
lowDriver = new LowResFact();// 实例化低分 辨率驱动对象
highDriver = new HighResFact();// 实例化高 分辨率驱动对象
}//end ApControl()
public void displayDriver()
{
lowDisplayDriver = lowDriver.getDispDrvr();// 得到低分辨率驱动
lowDisplayDriver.dDriver();// 低分辨率显示驱动
highPrintDriver = highDriver.getPrtDrvr();// 得到低分辨率驱动
highPrintDriver.pDriver();// 高分辨率显示驱动
}//end displayDriver()
public static void main(String[] args)
{
System.out.println("Abstract Factory");
ApControl ac = new ApControl();
ac.displayDriver();
}//end main(...)
}//end class ApControl
输出结果如下:
Abstract Factory
低分辨率 ----> 驱动
高分辨率 ----> 驱动
低分辨率 __ 显示驱动
显示出 __ 低分辨率图像
高分辨率 -- 打印驱动
打印 -- 高分辨率图像
Abstract Factory 模式适用性:
l 在以下情况可以使用 Abstract Factory 模式:
l 一个系统 要独立于他的产品的创建、组合和表示时;
l 一个系统 要由多个产品系列中的一个来配置时;
l 当你要强 调一系列相关的产品对象的设计以便进行联合使用时;
l 当你提供 一个产品类库,而只想显示他们的接口而不是实现时。
在 Abstract Factory 模式中 ApControl 的责 任是知道如何与合适的对象协同工作; ResFactory 的责 任是提供合适的对象。
Abstract Factory 模式:关键特征
l 意图:你需要为 特定的客户(或情况)提供特定系列的对象。
l 问题:一系列相 关的对象需要被实例化。
l 解决方案:协调 不同系列对象的创建过程。提供一种方法保持“如何在客户对象外部执行兑现实例化”的规则,客户对象将使用这些实例化出来的对象。
l 参与者 与协作者: Abstract Factory 为 “如何创建需要的每一个系列的对象”定义接口。典型的情况下,每个系列都独立拥有自己的 ConcreteFactory ,通过它被实例化。
l 效果:这个模式 将“使用哪些对象”的规则与“如何使用这些对象”的逻辑相隔离。
l 实现: 定义一个抽象类来指定那些对象将被创建。然后为每个系列实现一个具体类。表或文件也可以被用于达到同样的目的 。
下面是 Abstract Factory 模式涉及的 3 个 关键策略:
1 . 发现 并封装变化点
“使用哪个驱动对象”的选择食变化的。所以,将它封装在 ResFactory 类中。
2 . 优先 使用对象组合,而不是类继承
将变化点放在一个独立的对象—— ResFactory 对象——中并让 ApControl 对象使用 ResFactory 对象,而不是拥有两类不同的 ApControl 对象。
3 . 针对 接口设计,而不是针对实现设计
ApControl 知道 怎样想 ResFactory 请求实 例化驱动对象——它不知道(或不关心) ResFactory 对象 实际如何响应这一请求。