Понимание абстрактной фабричной картины

Я читал об абстрактных фабричных шаблонах в вики. Но я не понимаю, на самом деле прибыль с использованием этого шаблона. Можете ли вы привести пример, в котором сложно избежать абстрактного фабричного шаблона. Рассмотрим следующий код 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 раз в коде, тогда мы можем использовать просто новый оператор. А зачем нам нужна абстрактная фабрика?

3 ответа

Решение

Вам не хватает половины работы:)

void processOrder(FinancialToolsFactory ftf,Order o) {

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

этот код работает так же, как вы проходите канадскую или европейскую реализацию FinancialToolsFactory (вы можете экспортировать класс разработчика во внешний ресурс и создать его, например, с помощью Class.newInstance()).

В этом случае одно из реальных преимуществ использования шаблонов заключается не в написании кода, который реализует шаблон, а в том, кто использует этот код!

PS: мой ответ намеренно неполон, и попробуйте ответить только на этот конкретный вопрос; обсуждение шаблонов и их преимуществ слишком велико!

Вы воспользуетесь этим паттерном, если будете прозрачно поддерживать различные реализации. Передавая решение о том, какую реализацию использовать на фабрике, в вашем коде есть единственная точка, в которой принимается это решение (так называемая единая ответственность).

Абстрактный шаблон фабрики расширяет эту концепцию, объединяя связанные фабрики, такие как фабрики различных финансовых инструментов в вашей выборке.

Теперь, если вы только один или два раза создаете экземпляры своих финансовых инструментов в своем коде, использование фабрик является чрезмерной разработкой. Выгода приходит, когда вам нужно многократно создавать экземпляры разных реализаций одного и того же интерфейса в разных местах, и вы хотите иметь возможность работать, не беспокоясь о том, какую реализацию вы используете или как принимается это решение.

В Интернете есть довольно много ресурсов об этом шаблоне, и трудно предположить, что может быть лучшим способом объяснить его назначение так, чтобы это звучало "правдоподобно" для вас.

Но я думаю, что ключевым моментом является:

С этим шаблоном тому, кто хочет создать экземпляр конкретной реализации интерфейса, не нужно знать, что это за конкретная реализация. Призыв к new Оператор скрыт внутри фабрики, и пользователю фабрики не нужно знать конкретный класс.

Это облегчает переключение реализации позже: вам не нужно находить и настраивать все места, где new ConcreteClass() был вызван и измените его на new OtherConcreteClass() для того, чтобы использовать другую реализацию. Вы просто проходите мимо другой фабрики, и каждый, кто использует эту фабрику, автоматически создает экземпляры OtherConcreteClass (даже не зная, что он делает это...)

Другие вопросы по тегам