«1. Введение

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

Шаблоны проектирования приобрели популярность после того, как в 1994 году была опубликована книга Эриха Гаммы, Джона Влиссидеса, Ральфа Джонсона и Ричарда Хелма (также известная как Банда четырех или GoF) «Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения».

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

2. Креативные шаблоны проектирования

Креативные шаблоны проектирования связаны со способом создания объектов. Они уменьшают сложность и нестабильность, создавая объекты контролируемым образом.

Новый оператор часто считается вредным, так как он разбрасывает объекты по всему приложению. Со временем может стать сложно изменить реализацию, потому что классы становятся тесно связанными.

Creational Design Patterns решает эту проблему, полностью отделяя клиента от фактического процесса инициализации.

В этой статье мы обсудим четыре типа творческого шаблона проектирования:

  1. Singleton – Ensures that at most only one instance of an object exists throughout application
  2. Factory Method – Creates objects of several related classes without specifying the exact object to be created
  3. Abstract Factory – Creates families of related dependent objects
  4. BuilderConstructs complex objects using step-by-step approach

Давайте теперь подробно обсудим каждый из этих шаблонов.

3. Шаблон проектирования Singleton

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

Класс Singleton также предоставляет одну уникальную глобальную точку доступа к объекту, так что каждый последующий вызов точки доступа возвращает только этот конкретный объект.

3.1. Пример шаблона Singleton

Несмотря на то, что шаблон Singleton был представлен GoF, исходная реализация известна как проблематичная в многопоточных сценариях.

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

public class Singleton  {    
    private Singleton() {}
    
    private static class SingletonHolder {    
        public static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {    
        return SingletonHolder.instance;    
    }
}

Здесь мы создали статический внутренний класс, который содержит экземпляр класса Singleton. Он создает экземпляр только тогда, когда кто-то вызывает метод getInstance(), а не при загрузке внешнего класса.

Это широко используемый подход для класса Singleton, поскольку он не требует синхронизации, является потокобезопасным, обеспечивает ленивую инициализацию и имеет сравнительно меньше шаблонов.

Также обратите внимание, что у конструктора есть модификатор доступа private. Это требование для создания Singleton, поскольку общедоступный конструктор означает, что любой может получить к нему доступ и начать создавать новые экземпляры.

Помните, что это не оригинальная реализация GoF. Оригинальную версию можно найти в этой связанной статье Baeldung об синглтонах в Java.

3.2. Когда использовать шаблон проектирования Singleton

    Для ресурсов, которые дорого создавать (например, объекты соединения с базой данных) Хорошей практикой является хранение всех регистраторов как Singleton, что повышает производительность Классы, предоставляющие доступ к параметрам конфигурации для приложения Классы, содержащие ресурсы, которые доступ в общем режиме

4. Шаблон проектирования фабричных методов

Шаблон проектирования фабрики или фабричный метод проектирования является одним из наиболее часто используемых шаблонов проектирования в Java.

Согласно GoF, этот шаблон «определяет интерфейс для создания объекта, но позволяет подклассам решать, экземпляр какого класса создавать. Метод Factory позволяет классу отложить создание экземпляров до подклассов».

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

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

4.1. Пример шаблона проектирования фабричного метода

«В этом примере мы создадим интерфейс Polygon, который будет реализован несколькими конкретными классами. PolygonFactory будет использоваться для выборки объектов из этого семейства:

Давайте сначала создадим интерфейс Polygon:

public interface Polygon {
    String getType();
}

Затем мы создадим несколько реализаций, таких как Square, Triangle и т. д., которые реализуют этот интерфейс и возвращают объект типа Polygon.

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

public class PolygonFactory {
    public Polygon getPolygon(int numberOfSides) {
        if(numberOfSides == 3) {
            return new Triangle();
        }
        if(numberOfSides == 4) {
            return new Square();
        }
        if(numberOfSides == 5) {
            return new Pentagon();
        }
        if(numberOfSides == 7) {
            return new Heptagon();
        }
        else if(numberOfSides == 8) {
            return new Octagon();
        }
        return null;
    }
}

4.2. Когда следует использовать шаблон проектирования фабричных методов

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

    5. Шаблон проектирования \»Абстрактная фабрика\»

В предыдущем разделе мы увидели, как можно использовать шаблон проектирования \»Фабричный метод\» для создания объектов, относящихся к одному семейству.

Напротив, шаблон проектирования Abstract Factory используется для создания семейств связанных или зависимых объектов. Его также иногда называют фабрикой фабрик.

Подробное объяснение можно найти в нашем учебнике по абстрактной фабрике.

6. Шаблон проектирования \»Строитель\»

Шаблон проектирования \»Строитель\» — это еще один шаблон создания, предназначенный для создания сравнительно сложных объектов.

Когда сложность создания объекта увеличивается, шаблон Builder может отделить процесс создания экземпляра, используя другой объект (строитель) для создания объекта.

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

6.1. Пример шаблона Builder

Оригинальный шаблон проектирования Builder, представленный GoF, ориентирован на абстракцию и очень хорош при работе со сложными объектами, однако его дизайн немного сложен.

Джошуа Блох в своей книге «Эффективная Java» представил улучшенную версию шаблона компоновщика, которая является чистой, легко читаемой (поскольку она использует плавный дизайн) и простой в использовании с точки зрения клиента. В этом примере мы обсудим эту версию.

В этом примере есть только один класс, BankAccount, который содержит построитель как статический внутренний класс:

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

public class BankAccount {
    
    private String name;
    private String accountNumber;
    private String email;
    private boolean newsletter;

    // constructors/getters
    
    public static class BankAccountBuilder {
        // builder code
    }
}

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

Мы определили BankAccountBuilder в статическом внутреннем классе:

Обратите внимание, что мы объявили тот же набор полей, что и внешний класс. Любые обязательные поля необходимы в качестве аргументов для конструктора внутреннего класса, а остальные необязательные поля можно указать с помощью методов установки.

public static class BankAccountBuilder {
    
    private String name;
    private String accountNumber;
    private String email;
    private boolean newsletter;
    
    public BankAccountBuilder(String name, String accountNumber) {
        this.name = name;
        this.accountNumber = accountNumber;
    }

    public BankAccountBuilder withEmail(String email) {
        this.email = email;
        return this;
    }

    public BankAccountBuilder wantNewsletter(boolean newsletter) {
        this.newsletter = newsletter;
        return this;
    }
    
    public BankAccount build() {
        return new BankAccount(this);
    }
}

Эта реализация также поддерживает гибкий подход к проектированию, поскольку методы установки возвращают объект построителя.

Наконец, метод сборки вызывает закрытый конструктор внешнего класса и передает себя в качестве аргумента. Возвращенный BankAccount будет создан с параметрами, установленными BankAccountBuilder.

Давайте посмотрим на краткий пример шаблона построителя в действии:

6.2. Когда использовать шаблон Builder

BankAccount newAccount = new BankAccount
  .BankAccountBuilder("Jon", "22738022275")
  .withEmail("[email protected]")
  .wantNewsletter(true)
  .build();

7. Заключение

  1. When the process involved in creating an object is extremely complex, with lots of mandatory and optional parameters
  2. When an increase in the number of constructor parameters leads to a large list of constructors
  3. When client expects different representations for the object that’s constructed

В этой статье мы узнали о порождающих шаблонах проектирования в Java. Мы также обсудили их четыре различных типа, то есть Singleton, Factory Method, Abstract Factory и Builder Pattern, их преимущества, примеры и когда мы должны их использовать.

Как всегда, полные фрагменты кода доступны на GitHub.

«