跳到主要内容

设计模式之抽象工厂模式

抽象工厂模式定义

抽象工厂模式(Abstract Factory)是从工厂方法模式改进而来的。在工厂方法模式中,我们的工厂只能生产一种产品,但实际可能需要的是一系列的产品。抽象工厂模式使得我们能够从工厂中获得相关的一些列产品。调用者并不关心这一些列产品如何实现,也不关心这些产品叫什么,它只关心该使用哪个工厂。

抽象工厂模式的实现

// 抽象工厂
public abstract class AbstractFactory {
public abstract AbstractProductTypeA createProductA();
public abstract AbstractProductTypeB createProductB();
}

// 抽象产品
public abstract class AbstractProductTypeA {
public abstract void something();
}

public abstract class AbstractProductTypeB {
public abstract void something();
}

// 具体工厂和具体产品
public class FactoryA extends AbstractFactory {
@Override
public AbstractProductTypeA createProductA() {
return new ProductBrandATypeA();
}

@Override
public AbstractProductTypeB createProductB() {
return new ProductBrandATypeB();
}
}

public class ProductBrandATypeA extends AbstractProductTypeA {
@Override
public void something() {
System.out.println("品牌A 类型A");
}
}

public class ProductBrandATypeB extends AbstractProductTypeB {
@Override
public void something() {
System.out.println("品牌A 类型B");
}
}

public class FactoryB extends AbstractFactory {
@Override
public AbstractProductTypeA createProductA() {
return new ProductBrandBTypeA();
}

@Override
public AbstractProductTypeB createProductB() {
return new ProductBrandBTypeB();
}
}

public class ProductBrandBTypeA extends AbstractProductTypeA {
@Override
public void something() {
System.out.println("品牌B 类型A");
}
}

public class ProductBrandBTypeB extends AbstractProductTypeB {
@Override
public void something() {
System.out.println("品牌B 类型B");
}
}

测试:

public class Main {
public static void main(String[] args) {
create(new FactoryA());
create(new FactoryB());
}
public static void create(AbstractFactory factory){
AbstractProductTypeA typeA = factory.createProductA();
AbstractProductTypeB typeB = factory.createProductB();
typeA.something();
typeB.something();
}
}

结果:

品牌A 类型A
品牌A 类型B
品牌B 类型A
品牌B 类型B

使用抽象工厂模式或者工厂方法模式,可以很方便的按照具体的需求变更实现而不大量改动代码。一个最常见的例子是同一套代码兼容不同数据库。由于不同的数据库之间的接口都有各自的差异,针对某个数据库编写的代码很有可能在另一个数据库上失效。使用抽象工厂模式后,对数据库的操作便统一了。上方代码解决了更换不同实现时大量修改代码的问题,但还存在频繁修改具体工厂的问题。这一问题,我们使用依赖注入(Dependency Injection)解决。

public class Main {
// 具体工厂A
public static final String FACTORY_A = "cool.czm.design.af.FactoryA";
// 具体工厂B
public static final String FACTORY_B = "cool.czm.design.af.FactoryB";

public static void main(String[] args) throws Exception {
create(getFactoryInstance(FACTORY_A));
create(getFactoryInstance(FACTORY_B));
}

// 通过反射创建具体工厂,创建什么工厂由外部配置决定
public static AbstractFactory getFactoryInstance(String className) throws Exception {
return (AbstractFactory) Class.forName(className).newInstance();
}

public static void create(AbstractFactory factory) {
AbstractProductTypeA typeA = factory.createProductA();
AbstractProductTypeB typeB = factory.createProductB();
typeA.something();
typeB.something();
}
}

利用Java反射机制,变更相关工厂并不需要修改代码,仅需要修改相关配置文件即可。甚至正在运行的程序也可动态的变更工厂。对于工厂相关的模式,都可以尝试使用反射注入相关依赖,避免修改代码。