一、抽象工厂模式简介(摘自GOF《设计模式》):
抽象工厂模式的意图是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂模式的UML图如下:
如图所示,在抽象工厂模式中,客户程序只知道抽象的工厂和抽象的产品,在这种情况下编程,真正做到了针对接口编程而不是针对实现编程。
二、jdk中的抽象工厂模式:
抽象工厂模式是23个设计模式中的第一个,应用不可谓不广泛,所以在jdk的源码中也有很多应用抽象工厂的地方,在这里我举的例子来自Calendar类。
Calendar类的getInstance()方法就是抽象工厂应用的绝佳例子,Calendar(相当于抽象工厂)根据Client传入的不同参数实例化不同的类(即得到不同的产品),实现了抽象工厂模式。我就不废话了,直接上代码:
public static Calendar getInstance(TimeZone zone,
Locale aLocale)
{
return createCalendar(zone, aLocale);
}
调用的createCalendar方法的源码如下:
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
// If the specified locale is a Thai locale, returns a BuddhistCalendar
// instance.
if ("th".equals(aLocale.getLanguage())
&& ("TH".equals(aLocale.getCountry()))) {
return new sun.util.BuddhistCalendar(zone, aLocale);
} else if ("JP".equals(aLocale.getVariant())
&& "JP".equals(aLocale.getCountry())
&& "ja".equals(aLocale.getLanguage())) {
return new JapaneseImperialCalendar(zone, aLocale);
}
// else create the default calendar
return new GregorianCalendar(zone, aLocale);
}
阅读上面代码,不难看出,在这个抽象工厂中有3个具体产品,分别是:BuddhistCalendar、JapaneseImperialCalendar以及GregorianCalendar,抽象工厂根据不同的条件创建不同的具体产品,而返回的接口依然是抽象产品接口。
它跟书本上的教课书式的抽象工厂模式还是有区别的:很明显,这里的抽象工厂(Calendar类)和抽象产品(Calendar类)是同一个类,但我依然认为calendar是一个抽象工厂的实现,因为,做设计变通是必须的,尽信书,则不如无书!
三、关于抽象工厂的思考
抽象工厂模式在23个经典设计模式中算是比较简单的一个,实现它并不复杂,但是与关注它的实现相比,我更关注它的应用。抽象工厂模式适用于设计中强调一系列相关产品对象的情况,在这种情况下使用抽象工厂模式能够分离接口与实现,使我们能够针对接口编程而非针对实现,这样带来一个好处:使我们更方便的交换产品系列(只需更换一次具体工厂的实现即可)。
同时,抽象工厂模式也有一个致命的缺点:难以支持新种类的产品,从UML图中可以看出,AbstractFactory支持的产品种类是写死的,当要增加一个新产品时,整个AbstractFactory继承体系都必须重构,这是十分麻烦的!幸亏,这种灾难性的情况并非不可避免,一种更灵活的设计是给创建对象的操作增加一个参数,该参数指定了将被创建对象的种类,Calendar类就是用了这种方法,如果它想增加一个产品,只需在createCalendar方法中多加一个else if语句即可,灵活而方便!