GOF《设计模式》一书对Abstract Factory模式是这样描述的:
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
大致意思是说:我们在创建这些对象的时候,并不需要指定它们的具体类,这些具体类的对象是由工厂对象负责实例化的。下面是《Design Patterns Explained》一书的例子,有关计算机系统的显示和打印程序,用来显示和打印的分辨率取决于当前运行的系统。低端机使用低分辨率的显示和打印驱动程序,高端机使用高分辨率的显示和打印驱动程序。其结构图如下:
代码如下:
abstract class ResFactory{
abstract public DisplayDriver getDisplayDrvr();
abstract public PrintDriver getPrintDrvr();
}
class LowResFact extends ResFactory{
public DisplayDriver getDisplayDrvr() {
returnnew LRDD();
}
public PrintDriver getPrintDrvr() {
returnnew LRPD();
}
}
class HighResFact extends ResFactory{
public DisplayDriver getDisplayDrvr() {
returnnew HRDD();
}
public PrintDriver getPrintDrvr() {
returnnew HRPD();
}
}
abstract class DisplayDriver{
}
abstract class PrintDriver{
}
class HRDD extends DisplayDriver{
public HRDD() {
System.out.println("使用高端机的显示驱动程序")
}
}
class LRDD extends DisplayDriver{
public LRDD(){
System.out.println("使用低端机的显示驱动程序");
}
}
class HRPD extends PrintDriver{
public HRPD() {
System.out.println("使用高端机的打印驱动程序");
}
}
class LRPD extends PrintDriver{
public LRPD() {
System.out.println("使用低端机的打印驱动程序");
}
}
public class ApControl {
public static ResFactory getResFactory(ResFactory factory){
return factory;
}
public static void main(String[] args) {
ResFactory highResFact=ApControl.getResFactory(new HighResFact());
highResFact.getDisplayDrvr();
highResFact.getPrintDrvr();
ResFactory lowResFact=ApControl.getResFactory(new LowResFact());
lowResFact.getDisplayDrvr();
lowResFact.getPrintDrvr();
}
}输出结果:
使用高端机的显示驱动程序
使用高端机的打印驱动程序
使用低端机的显示驱动程序
使用低端机的打印驱动程序
在这个例子中ApControl使用派生自两个不同的服务类(DisplayDriver和PrintDriver)的对象。这个设计非常简化,隐藏了实现细节,系统的可维护性也更好。ApControl不知道自己拥有的服务对象的那个特定具体实现,因为创建对象是工厂的职责。ApControl也不知道自己使用的是哪个特定工厂,因为它只知道自己有一个ResFactory对象。它可能是一个HighResFact也可能是一个LowResFact,但它不知道到底是哪一个。
小结:在必须协调一组对象的创建时,可以应用Abstract Factory模式。它提供了一种方式,将如何执行对象实例化的规则从使用这些对象的客户对象中提取出来。首先,找出实例化的规则,定义了一个带接口的抽象类,其中的接口为每种需要实例化的对象提供一个方法。然后,从这个类为每个组实现具体类。最后,由客户对象决定使用具体工厂来创建所需的对象。它主要适用于以下几种情况:
1) 一个系统要独立于它的产品的创建、组合和表示时。
2) 可以对系统进行配置,以便系统可以使用多个产品系列中的某一个。
3) 当需要强调一系列相关产品对象的设计以便进行联合使用时。
4) 当希望提供一个产品类库,而只想显示他们的接口而不是实现时。