了解抽象工厂模式

时间:2014-02-11 15:41:32

标签: java design-patterns factory-pattern

我在wiki上读到了关于抽象工厂模式的内容。但我不明白使用这种模式真的有利可图。你能得到一个很难避免抽象工厂模式的例子吗?请考虑以下Java代码:

public abstract class FinancialToolsFactory {
    public abstract TaxProcessor createTaxProcessor();
    public abstract ShipFeeProcessor createShipFeeProcessor();
}

public abstract class ShipFeeProcessor {
    abstract void calculateShipFee(Order order);
}

public abstract class TaxProcessor {
    abstract void calculateTaxes(Order order);
}

// Factories
public class CanadaFinancialToolsFactory extends FinancialToolsFactory {
    public TaxProcessor createTaxProcessor() {
        return new CanadaTaxProcessor();
    }
    public ShipFeeProcessor createShipFeeProcessor() {
        return new CanadaShipFeeProcessor();
    }
}

public class EuropeFinancialToolsFactory extends FinancialToolsFactory {
   public TaxProcessor createTaxProcessor() {
        return new EuropeTaxProcessor();
    }
    public ShipFeeProcessor createShipFeeProcessor() {
        return new EuropeShipFeeProcessor();
    }
}

// Products
public class EuropeShipFeeProcessor extends ShipFeeProcessor {
    public void calculateShipFee(Order order) {
        // insert here Europe specific ship fee calculation
    }
}   

public class CanadaShipFeeProcessor extends ShipFeeProcessor {
    public void calculateShipFee(Order order) {
        // insert here Canada specific ship fee calculation
    }
}

public class EuropeTaxProcessor extends TaxProcessor {
    public void calculateTaxes(Order order) {
        // insert here Europe specific tax calculation
    }
}

public class CanadaTaxProcessor extends TaxProcessor {
    public void calculateTaxes(Order order) {
        // insert here Canada specific tax calculation
    }
}

如果我们需要在代码中创建1-2代以下的代码中的对象,那么我们就可以使用new运算符。为什么我们需要在抽象工厂?

3 个答案:

答案 0 :(得分:3)

如果您要透明地支持不同的实现,那么您将利用此模式。通过将要使用的实现的决定委托给工厂,您在代码中有一个点可以做出决定(a.k.a。单一责任)。

抽象工厂模式通过聚合相关工厂(例如样本中的不同金融工具工厂)来实现这一概念。

现在,如果您只在代码中实例化一次或两次财务工具,那么使用工厂就会过度工程化。当您需要多次在不同位置实例化相同接口的不同实现并且您希望能够工作而不必担心您正在使用哪个实现或如何做出决策时,就会获得收益。

答案 1 :(得分:2)

你缺少了一半的工作:)

void processOrder(FinancialToolsFactory ftf,Order o) {

  tft.createTaxProcessor().calculateTaxes(o);
  tft.createShipFeeProcessor().calculateShipFee(o);
}

此代码与您传递FinancialToolsFactory的加拿大或欧洲实现一样有效(例如,您可以将实现者类外部化为外部资源并使用Class.newInstance()进行实例化。)

在这种情况下,模式使用的一个真正好处是不是编写实现模式的代码,而是使用该代码的人!

PS:我的回答是故意不完整的,试着回答这个具体的问题;关于模式及其好处的讨论太大了!

答案 2 :(得分:2)

在网络上有关于这种模式的相当多的资源,很难猜出什么是以对你来说听起来“合理”的方式解释其目的的最佳方式。

但我认为关键点是:

使用此模式,想要创建接口的特定实现的实例的人不需要知道此特定实现的内容。对new运算符的调用隐藏在工厂内部,工厂用户不需要知道具体类。

这使得以后更容易切换实现:您不必查找并调整调用new ConcreteClass()的所有位置,并将其更改为new OtherConcreteClass()以使用其他实现。你只是通过一个不同的工厂,使用这个工厂的每个人都自动创建OtherConcreteClass的实例(甚至不知道他这样做......)