Абстрактное использование фабричного шаблона проектирования

Я пытаюсь изучить творческие шаблоны проектирования, и я думаю, что теперь понимаю шаблон Factory Method. Но при переходе на абстрактный заводской шаблон я не смог найти ему применение. Я знаю, что я что-то пропустил с этим, но не знаю, где.

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

public interface CarFactory{
    public Car getCar();
}

И наши бетонные заводы будут чем-то вроде

public class AudiFactory{
    public Car getCar(){
        return new Audi();
    }
}

public class VolvoFactory{
    public Car getCar(){
        return new Volvo();
    }
}

И в пользовательском классе мы будем использовать его как

CarFactory factory = new AudiFactory();
Car carAudi = factory.getCar();
factory = new VolvoFactory();
Car carVolvo = factory.getCar();

Я думаю, что мы можем создать ту же функциональность и с помощью Factory Pattern.

public class CarFactory{

    public Car getCar(String make){
    if("Audi".equals(make))
        return new Audi();
    else if("Volvo".equals(make))
        return new Volvo();
    }
}

И в пользовательском классе мы можем

CarFactory factory = new CarFactory();
Car carAudi = factory.getCar("Audi");
Car carVolvo = factory.getCar("Volvo");

Если я правильно понимаю (пожалуйста, поправьте меня, если это неправильно), зачем нам для этого нужен еще один шаблон проектирования?


person Jomy George    schedule 01.10.2015    source источник
comment
Вы читали книгу о шаблонах проектирования GoF?   -  person Adam Arold    schedule 01.10.2015
comment
Он предназначен для абстрагирования создания объекта, клиентский класс, например, ожидает получить конструктор CarFactory to и использовать его для создания автомобиля, клиентскому классу все равно, какой это автомобиль, и он не должен этого знать. Если вы читали книгу GoF, возможно, прочитайте ее еще раз; клиентский класс никогда не должен создавать фабрику сам по себе.   -  person Łukasz    schedule 01.10.2015
comment
Вы можете проверить этот вопрос. В нем много полезных примеров из JDK.   -  person Adam Arold    schedule 01.10.2015
comment
Спасибо, Лукаш, но нельзя ли создать клиентский класс со строковым значением, представляющим тип автомобиля (Audi или Volvo) в его конструкторе? так же, как экземпляр Factory?   -  person Jomy George    schedule 01.10.2015


Ответы (4)


Для вашего примера, да, вы правы, фабричный шаблон может заменить абстрактный фабричный шаблон.

Абстрактная фабрика имеет смысл, когда вам нужно создавать разные продукты одного семейства, не зная семейства (Volvo или Audi).

interface Car {}
interface Engine {}
interface Gear {}

interface ICarFactory {
    Car createCar();
    Engine createEngine();
    Gear createGear();
}

class AudiCar implements Car {}
class AudiEngine implements Engine {}
class AudiGear implements Gear {}

class AudiFactory implements ICarFactory {
    public Car createCar() { return new AudiCar(); }
    public Engine createEngine() { return new AudiEngine(); }
    public Gear createGear() { return new AudiGear(); }
}

Я считаю, что вы можете представить то же самое для Volvo.

Теперь предположим, что у нас есть класс, который строит Car, и ему все равно, Audi это или Volvo.

class CarBuilder {
    public static Car buildCar(ICarFactory factory) {
        Car car = factory.createCar();

        car.setEngine(factory.createEngine());
        car.setGear(factory.createGear());

        return car;
    }
}

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

person Mehmet Ataş    schedule 01.10.2015

В вашем примере:

  • Factory Method Pattern - это шаблон для создания автомобиля (скрыть реализацию создания автомобиля)

  • Абстрактный заводской шаблон - это шаблон для создания автомобильного завода (создание автомобильного завода, а не создание автомобиля, фокус на создании завода)

  • Итак, вы можете подумать: паттерн Abstract Factory — это паттерн для создания Factory of Factory.

  • Эти два шаблона предназначены для разных целей.

Абстрактный заводской шаблон (реализация с использованием интерфейса/абстракции) + шаблон IoC -> помочь вам решить, какой тип фабрики автомобилей используется во время выполнения, а не во время компиляции (шаблон метода фабрики не подходит для этих требований)

person Loc    schedule 01.10.2015
comment
как создается экземпляр абстрактной фабрики - это отдельное обсуждение от того, зачем вам это нужно в первую очередь - person Kalpesh Soni; 01.10.2015

Вы очень хорошо поняли использование шаблона Factory: Factory позволяет создавать объекты, тип которых неизвестен во время компиляции (конечно, просто подкласс интерфейса). Теперь сделайте шаг вперед:

Прямо сейчас у вас есть один CarFactory для создания Car объектов. Но как вы справитесь, если вам нужно несколько фабрик одновременно в вашей программе?

Вот когда на помощь приходит Абстрактная фабрика: Абстрактная фабрика — это фабрика фабрик, которая позволяет вам создавать фабрики, тип которых неизвестен во время компиляции: Итак, у вас будет

public interface AbstractCarFactory
{
    public CarFactory getCarFactory(String area);
}

... и вы сможете реализовать EuropeanCarFactory, AmericanCarFactory и т.д.


Другой пример, когда абстрактная фабрика полезна, — это когда у вас есть класс фабрики с параметрами в его конструкторе:

public CarFactory
{
    public CarFactory(boolean cheatingMotor) {...}
}

Создать один объект CarFactory с помощью динамического создания экземпляров (Class.forName("CarFactory").newInstance()) сложно, поэтому полезен еще один уровень факторизации вверх: абстрактная фабрика, которая решает, как создавать экземпляр CarFactory:

public interface AbstractCarFactory
{
    public CarFactory(boolean cheatingMotor);
}

public class MyAbstractCarFactory implements AbstractFactory
{
    public CarFactory(boolean cheatingMotor)
    {
        return new CarFactory(true);
    }
}

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

person Little Santi    schedule 01.10.2015

Подумайте об объекте java.sql.Connection. Для меня это абстрактная фабрика.

Он создает для вас Statement, CallableStatement и т. д.

Внутри это может быть OracleStatement или MySQLStatement.

Ваш клиентский код чист, и ему все равно, как он внутренне подключает сокет к серверу БД.

См. также Шаблоны проектирования: абстрактная фабрика и фабричный метод

О вашем исходном коде

Подумайте о реальном мире, автомобили GM не производятся на «Фабрике» Toyota или на каком-то заводе Generic :)

Чего вы достигли, так это избавления от if-else. Подумайте о том, чтобы изучить весь список шаблонов проектирования, чтобы просто избавиться от if-else в вашем коде.

Если бы у Sun был конечный набор баз данных, с которыми нужно было бы иметь дело, они могли бы написать некоторые из них, если бы еще

Факт

1) Драйвер SQL не написан Sun 2) с помощью этого шаблона вы можете «внедрить» любой драйвер в свой код, не беспокоясь о том, как он работает, просто полагаясь на интерфейсы

просить клиента передавать "Ауди" на каждый звонок просто неразумно

person Kalpesh Soni    schedule 01.10.2015
comment
Даже если мы используем Factory Pattern, мы можем добиться того же. что, если java.sql.Connection является FactoryPattern, который принимает строку, которая представляет OracleStatement или MySQLStatement. Я вижу случай передачи некоторых недопустимых значений. - person Jomy George; 01.10.2015