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

Шаблоны креативного проектирования сосредоточены на абстрагировании процесса создания экземпляров. Они помогают сделать систему независимой от того, как создаются, компонуются и представляются ее объекты. Порождающие шаблоны проектирования можно разделить на две группы: шаблоны создания классов, которые используют наследование, и шаблоны создания объектов, которые делегируют создание экземпляров другому объекту. В этом посте мы кратко обсудим 5 творческих паттернов, отмеченных Бандой четырех.

Абстрактная фабрика

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

Абстрактная фабрика — это объект, используемый для создания семейств объектов. В то время как фабричный метод удаляет особенности того, как создаются объекты, абстрактная фабрика удаляет особенности того, как создаются эти фабрики. Из-за этого абстрактная фабрика также широко известна как «Фабрика фабрик».

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

Строитель

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

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

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

Заводской метод

С фабричным методом вы предоставляете интерфейс, который будет использоваться для создания объектов, но позволяете подклассам решать, какой класс создавать. Возвращаясь к примеру с автомобилем, когда пользователь заказывает гамбургер, он не делает его сам, а просто просит тот, который ему нужен. Вы можете думать о ресторане как о фабрике. Клиент делает запрос, предоставляя интерфейс (гамбургер), затем factory будет полагаться на подклассы, чтобы решить, какой тип гамбургера сделать (чизбургер, вегетарианский бургер и т. д.). После завершения работы подкласса фабрика вернет результат клиенту.

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

Прототип

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

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

Синглтон

Синглтон — это класс, который может быть создан только один раз. После создания программа получает глобальную точку доступа к этому классу. Синглтон может быть создан одним из двух способов: ленивым или нетерпеливым. Ленивый способ проверяет, существует ли экземпляр класса перед созданием экземпляра. Нетерпеливый способ всегда будет возвращать новый экземпляр класса. Легко думать, что ленивый способ — лучший вариант, и в большинстве случаев это так, но нетерпеливый способ также может быть полезен. Если вы знаете, что стоимость создания экземпляра не так уж велика или что при запуске вашей программы всегда будет создаваться новый экземпляр, то способ с энтузиазмом может оказаться для вас подходящим методом создания экземпляра.

Этот шаблон полезен, когда вам нужен только один экземпляр класса. Например, если вы делаете видеоигру, вам понадобится только один экземпляр отображения счета игрока. В этом случае синглтон был бы полезным шаблоном проектирования. Еще одно соображение, которое следует учитывать при принятии решения об использовании одноэлементного шаблона, — это потокобезопасность. Вышеупомянутые методы создания экземпляров прекрасно работали бы в однопоточном приложении, но в многопоточном приложении потенциал для нескольких объектов одного и того же класса возрастает. Это может быть связано с тем, что каждый поток получает доступ к проверке null (в случае отложенного создания экземпляра) в разное время.