Шаблоны дизайна GoF: различные виды фабрики - PullRequest
0 голосов
/ 11 января 2019

Некоторое время я использую шаблоны проектирования GoF и обнаружил, что некоторые из них неправильно поняты.

Я сосредоточен на Фабрике (не Абстрактной Фабрике). До сих пор я думал, что Factory - это класс с несколькими креативными методами, такими как BorderFactory в Java API:

  • Граница b1 = BorderFactory.createLineBorder (Color.RED)
  • Border b2 = BorderFactory.createTitledBorder ("Hello")

Все методы, возвращающие один и тот же вид абстракции (например, интерфейс).

Однако я обнаружил, что «Фабрика» в GoF (настоящее имя «Метод фабрики») на самом деле не является классом такого типа, а классом с уникальным методом, возвращающим конкретный тип в зависимости от входного параметра (например, строка). Я использую этот тип фабрики для анализа (язык моделирования).

Образцами создания GoF являются Factory Method, Abstract Factory, Builder, Singleton и Prototype. Фабрики не существует, если только Фабрика не рассматривается как усовершенствованный Фабричный метод (слишком много входных параметров -> нужно определить несколько методов createXXX)?

Что вы думаете об этом?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Вы наткнулись именно на ситуацию, описанную авторами книги GoF спустя 15 лет после выпуска книги: http://www.informit.com/articles/article.aspx?p=1404056 Просто внимательно прочитайте -

Фабричный метод будет обобщен до Фабричного

Мое лучшее предложение людям - не помнить каноническую форму паттерна GoF или его реализации, а скорее помнить идею, лежащую в основе паттерна. Идея этого обобщенного шаблона Factory заключалась бы в предоставлении метода, который не является конструктором прямого класса и будет возвращать экземпляры его подклассов - либо как ссылки на интерфейсы (предпочтительно), либо как экземпляры подкласса. Действительно, в современных языках «каноническая» форма / реализация шаблонов GoF часто не имеет большого смысла, но идея, лежащая в основе каждого шаблона, как всегда, имеет смысл - применяется только при необходимости.

0 голосов
/ 11 января 2019

В ООП статические фабрики действительно не известны как шаблоны проектирования GOF.
Это методы, которые позволяют создавать и возвращать объекты.
Это имеет широкие намерения, такие как:

  • сокрытие для клиентов некоторых деталей реализации, таких как возвращаемый объект времени выполнения.
  • кэширование
  • проксирование.
  • облегчение использования API.
  • замена конструкторов

Обратите внимание, что фабрика static может не выполнять ничего из этого и просто использоваться как вспомогательный метод для создания объектов. Так что он может вообще не использовать функции ООП, что не относится к заводским методам и шаблонам проектирования GOF в целом.

Фабрики не существует, если только Фабрика не считается усовершенствованной Фабричный метод (слишком много входных параметров -> нужно определить несколько методы createXXX)?

IHMO фабричный метод выглядит как вариант статической фабрики.
У него нет такого же намерения, и он гораздо более специализирован: он не абстрагирует / не скрывает создания объекта, но делегирует его некоторым фабричным подклассам.
Также обратите внимание, что фабричный метод может также полагаться на статические фабрики для создания своих объектов, в то время как обратное менее очевидно.
Поэтому я считаю, что этот шаблон GOF создания более структурирован, чем фабрика static.

Пример для иллюстрации:

У Animal могут быть дети. У нас есть несколько подклассов Animal, и только подклассы Animal должны знать, какой экземпляр возвращается для своих детей.
Здесь мы хотим использовать фабричный метод, поскольку мы разрешаем задачу создания экземпляров подклассам.

Вы могли бы так сделать:

public abstract class Animal {
    public abstract ChildAnimal createChild(String name, LocalDate birthdate);
}

public class Dog extends Animal {

    @Override
    public ChildAnimal createChild(String name, LocalDate birthdate) {
        return new LittleDog(name, birthdate);
    }
}

public class Cat extends Animal {

    @Override
    public ChildAnimal createChild(String name, LocalDate birthdate) {
        return new LittleCat(name, birthdate);
    }
}

И так для ...

Хорошо, теперь предположим, что LittleCat имеет несколько конструкторов.
Это не делает API простым. Здесь мы могли бы использовать фабричные статические методы вместо конструкторов, чтобы прояснить ситуацию:

public class LittleCat implements ChildAnimal {


    static LittleCat withNameAndBirthDateAndParents(String name, LocalDate birthdate, Cat dad, Cat mom) {
        return new LittleCat("kitty", birthdate, dad, mom);
    }

    static LittleCat withNameAndBirthDate(String name, LocalDate birthdate) {
        return new LittleCat(name, birthdate, null, null);
    }

    static LittleCat withNoInformation() {
        return new LittleCat("kitty", LocalDate.now(), null, null);
    }


    private LittleCat(String name, LocalDate birthdate, Cat dad, Cat mom) {
        // implementation
    }
}

И теперь фабрика методов опирается на статическую фабрику:

public class Cat extends Animal {

    @Override
    public ChildAnimal createChild(String name, LocalDate birthdate) {
        return LittleCat.withNameAndBirthDate(name, birthdate);
    }
}
...