创建型模式之抽象工厂模式

编程

1 概述

上一篇文章讲到了工厂方法模式,它提供了一种在不指定具体实现的情况下,创建类实例的解决方案。那为什么还需要工厂模式" title="抽象工厂模式">抽象工厂模式呢?

2 抽象工厂模式

抽象工厂模式本质上,也是定义一个工厂,用来作为类创建的入口,拥有工厂方法模式的优点:如隐藏类的构造细节,降低类的使用复杂度,与调用者解耦等等。

而它与工厂方法模式最大的区别在于,抽象工厂模式更强调创建一族的元素。比如对于不同的浏览器,有不同的按钮,选择框和输入框。那么我们可以定义一个浏览器的接口,并创建浏览器工厂ChromeFactoryFirefoxFactory。其中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

回到顶部