创建型模式之抽象工厂模式
1 概述
上一篇文章讲到了工厂方法模式,它提供了一种在不指定具体实现的情况下,创建类实例的解决方案。那为什么还需要工厂模式" title="抽象工厂模式">抽象工厂模式呢?
2 抽象工厂模式
抽象工厂模式本质上,也是定义一个工厂,用来作为类创建的入口,拥有工厂方法模式的优点:如隐藏类的构造细节,降低类的使用复杂度,与调用者解耦等等。
而它与工厂方法模式最大的区别在于,抽象工厂模式更强调创建一族的元素。比如对于不同的浏览器,有不同的按钮,选择框和输入框。那么我们可以定义一个浏览器的接口,并创建浏览器工厂ChromeFactory
,FirefoxFactory
。其中ChromeFactory
可以创建Chrome
一族的按钮,选择框,FirefoxFactory
可以创建Firefox
一族的按钮选择框,从而实现同一族元素的高内聚,提高程序的灵活性和可扩展性。
3 案例
再看一个简单的例子。有一个汽车工厂,可以生产轿车和SUV。
interface CarFactory { Car getCar();
SUV getSUV();
}
interface Car {
void getSize();
}
interface SUV {
void getSize();
}
按类别,工厂又可以分为美国工厂和日本工厂。而日本工厂只能生产日本车,美国工厂只能生产美国车,这是绑定的关系:
class AmericanCarFactory implements CarFactory { [@Override](https://my.oschina.net/u/1162528)
public Car getCar() {
return new TeslaModalS();
}
[@Override](https://my.oschina.net/u/1162528)
public SUV getSUV() {
return new TeslaModalX();
}
}
public class TeslaModalS implements Car {
[@Override](https://my.oschina.net/u/1162528)
public void getSize() {
System.out.println("Size of American Car Modal S is "4979*1964*1445"");
}
}
public class TeslaModalX implements SUV {
[@Override](https://my.oschina.net/u/1162528)
public void getSize() {
System.out.println("Size of American SUV Modal X is "5037*2070*1684"");
}
}
class JapaneseCarFactory implements CarFactory {
[@Override](https://my.oschina.net/u/1162528)
public Car getCar() {
return new HondaAccord();
}
@Override
public SUV getSUV() {
return new HondaCRV();
}
}
public class HondaAccord implements Car {
@Override
public void getSize() {
System.out.println("Size of Japanese Car Accord is "4893*1862*1449"");
}
}
public class HondaCRV implements SUV {
@Override
public void getSize() {
System.out.println("Size of Japanese SUV C-RV is "4585*1855*1689"");
}
}
定义了上述工厂之后,我们便将同一族的产品,限制在了对应的工厂之中。然后我们再定义一个统一的入口,便可以很容易地创建汽车了:
public class Test { public static void main(String[] args) throws OperationNotSupportedException {
CarFactory japaneseCarFactory = CarFactoryProducer.createFactory(CarFactoryProducer.FactoryType.JAPANESE);
Car japaneseCar = japaneseCarFactory.getCar();
japaneseCar.getSize();
SUV japaneseSUV = japaneseCarFactory.getSUV();
japaneseSUV.getSize();
CarFactory americanCarFactory = CarFactoryProducer.createFactory(CarFactoryProducer.FactoryType.AMERICAN);
Car americanCar = americanCarFactory.getCar();
americanCar.getSize();
SUV americanSUV = americanCarFactory.getSUV();
americanSUV.getSize();
}
}
public abstract class CarFactoryProducer {
enum FactoryType {
JAPANESE, AMERICAN
}
public static CarFactory createFactory(FactoryType type) throws OperationNotSupportedException {
switch (type) {
case JAPANESE: return new JapaneseCarFactory();
case AMERICAN: return new AmericanCarFactory();
}
throw new OperationNotSupportedException("type "" + type + "" is not supported");
}
}
输出:
Size of Japanese Car Accord is "4893*1862*1449"Size of Japanese SUV C-RV is "4585*1855*1689"
Size of American Car Modal S is "4979*1964*1445"
Size of American SUV Modal X is "5037*2070*1684"
UML:
可以看到,抽象工厂模式极大地降低了类创建与使用的复杂度,提高了同一族元素的内聚性。同时,如果需要新增一族元素比如德国车,只需新增一个GermanyCarFactory
用来生产德国车即可,扩展性很好。
在JDK
中,DocumentBuilderFactory就运用了抽象工厂模式:
public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){ // 根据传入的参数,返回对应的Factory实现类
return FactoryFinder.newInstance(DocumentBuilderFactory.class, factoryClassName, classLoader, false);
}
4 总结
抽象工厂模式提供了创建一类元素的最佳方式,一般工厂类也都以Factory
字样结尾,并且创建方法返回一个子Factory
。当需要创建一组属于统一类别的类,并想要对外提供一个简单的接口时,请考虑使用抽象工厂模式。
文中例子的github地址
以上是 创建型模式之抽象工厂模式 的全部内容, 来源链接: utcz.com/z/514607.html