Абстрактная фабрика модель обеспечивает способ инкапсулировать группы отдельных заводов , которые имеют общую тему без указания их конкретных классов. [1] При обычном использовании клиентское программное обеспечение создает конкретную реализацию абстрактной фабрики, а затем использует общий интерфейс фабрики для создания конкретных объектов, которые являются частью темы. Клиент не знает (или уход) , какие конкретные объекты он получает от каждого из этих внутренних заводов, так как она использует только общие интерфейсы своих продуктов. [1]Этот шаблон отделяет детали реализации набора объектов от их общего использования и полагается на композицию объекта, поскольку создание объекта реализуется в методах, представленных в интерфейсе фабрики. [2]
Примером этого может быть абстрактный фабричный класс, DocumentCreator
который предоставляет интерфейсы для создания ряда продуктов (например, createLetter()
и createResume()
). Система могла бы иметь любое количество производных конкретных версий DocumentCreator
класса, таких как FancyDocumentCreator
или ModernDocumentCreator
, каждая с другой реализацией, createLetter()
и createResume()
которые создавали бы соответствующий объект, например FancyLetter
или ModernResume
. Каждый из этих продуктов является производным от простого абстрактного класса , как Letter
и Resume
из которого клиент знает. Клиентский код будет получить соответствующий экземпляр из DocumentCreator
и вызывать его фабричные методы. Каждый из результирующих объектов будет создан на основе одной DocumentCreator
и той же реализации и будет иметь общую тему (все они будут модными или современными объектами). Клиенту нужно только знать, как обращаться с абстрактным Letter
или Resume
классом, а не с конкретной версией, полученной от конкретной фабрики.
Завод является расположение класса бетона в коде , на которых построены объекты . Цель использования шаблона - изолировать создание объектов от их использования и создать семейства связанных объектов без необходимости зависеть от их конкретных классов. [2] Это позволяет вводить новые производные типы без изменения кода, использующего базовый класс .
Использование этого шаблона позволяет обмениваться конкретными реализациями без изменения кода, который их использует, даже во время выполнения . Однако использование этого шаблона, как и аналогичных шаблонов проектирования , может привести к ненужной сложности и дополнительной работе при первоначальном написании кода. Кроме того, более высокие уровни разделения и абстракции могут привести к тому, что системы будут сложнее отлаживать и поддерживать.
Обзор [ править ]
Шаблон проектирования Абстрактная фабрика [3] - один из двадцати трех хорошо известных шаблонов проектирования GoF, которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и многоразового объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить , тестирование и повторное использование.
Шаблон проектирования «Абстрактная фабрика» решает такие проблемы, как: [4]
- Как приложение может быть независимым от того, как создаются его объекты?
- Как класс может быть независимым от того, как создаются требуемые ему объекты?
- Как можно создать семейства связанных или зависимых объектов?
Создание объектов непосредственно внутри класса, которому требуются объекты, является негибким, потому что оно связывает класс с конкретными объектами и делает невозможным изменение экземпляра позже независимо от (без необходимости изменения) класса. Это предотвращает повторное использование класса, если требуются другие объекты, и затрудняет тестирование класса, поскольку реальные объекты не могут быть заменены фиктивными объектами.
Шаблон проектирования Абстрактная фабрика описывает, как решать такие проблемы:
- Инкапсулируйте создание объекта в отдельный (фабричный) объект. То есть определите интерфейс (AbstractFactory) для создания объектов и реализуйте интерфейс.
- Класс делегирует создание объекта объекту фабрики вместо того, чтобы создавать объекты напрямую.
Это делает класс независимым от того, как создаются его объекты (какие конкретные классы создаются). Класс может быть сконфигурирован с фабричным объектом, который он использует для создания объектов, и даже более того, фабричный объект может быть заменен во время выполнения.
Определение [ править ]
Суть шаблона абстрактной фабрики заключается в том, чтобы «предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов». [5]
Использование [ править ]
Завод определяет фактический конкретный тип объекта должен быть создан, и именно здесь , что объект на самом деле создается (в C ++, например, с помощью нового оператора ). Однако фабрика возвращает только абстрактный указатель на созданный конкретный объект .
Это изолирует клиентский код от создания объекта , поскольку клиенты просят объект фабрики создать объект желаемого абстрактного типа и вернуть абстрактный указатель на объект. [6]
Поскольку фабрика возвращает только абстрактный указатель, клиентский код (который запросил объект у фабрики) не знает - и не обременен - фактическим конкретным типом только что созданного объекта. Однако тип конкретного объекта (и, следовательно, конкретной фабрики) известен абстрактной фабрике; например, фабрика может прочитать его из файла конфигурации. Клиенту не нужно указывать тип, так как он уже указан в конфигурационном файле. В частности, это означает:
- Клиентский код ничего не знает о конкретном типе , и ему не нужно включать какие-либо файлы заголовков или объявления классов, связанные с ним. Клиентский код имеет дело только с абстрактным типом. Объекты конкретного типа действительно создаются фабрикой, но клиентский код обращается к таким объектам только через их абстрактный интерфейс . [7]
- Добавление новых конкретных типов выполняется путем изменения клиентского кода для использования другой фабрики, обычно это одна строка в одном файле. Затем другая фабрика создает объекты другого конкретного типа, но по-прежнему возвращает указатель того же абстрактного типа, что и раньше, тем самым изолируя клиентский код от изменений. Это значительно проще, чем изменение клиентского кода для создания экземпляра нового типа, что потребовало бы изменения каждого места в коде, где создается новый объект (а также обеспечения того, чтобы все такие места кода также знали о новом конкретном типе, путем включения, например, файла заголовка конкретного класса). Если все фабричные объекты хранятся глобально в синглтонеобъект, и весь клиентский код проходит через синглтон, чтобы получить доступ к надлежащей фабрике для создания объекта, тогда изменить фабрики так же просто, как изменить объект синглтона. [7]
Структура [ править ]
Диаграмма UML [ править ]
В приведенной выше UML диаграммы классов , то Client
класс , который требует ProductA
и ProductB
объектов не создавать экземпляры ProductA1
и ProductB1
классов непосредственно. Вместо этого Client
относится к AbstractFactory
интерфейсу для создания объектов, который не Client
зависит от того, как создаются объекты (какие конкретные классы создаются). Factory1
Класс реализует AbstractFactory
интерфейс путем создания экземпляра ProductA1
и ProductB1
классов.
В UML диаграмма последовательности показывает время выполнения взаимодействия: В Client
объектные вызовы createProductA()
на Factory1
объект, который создает и возвращает ProductA1
объект. После этого Client
звонки createProductB()
наFactory1
, который создает и возвращает ProductB1
объект.
Диаграмма Lepus3 [ править ]
Пример Python [ править ]
from abc import ABC , abstractmethod from sys import platform Кнопка класса ( ABC ): @abstractmethod def paint ( self ): passclass LinuxButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле Linux»class WindowsButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле Windows»class MacOSButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле MacOS»класс GUIFactory ( ABC ): @abstractmethod def create_button ( self ): passкласс LinuxFactory ( GUIFactory ): def create_button ( self ): return LinuxButton ()класс WindowsFactory ( GUIFactory ): def create_button ( self ): return WindowsButton ()класс MacOSFactory ( GUIFactory ): def create_button ( self ): return MacOSButton ()if platform == "linux" : factory = LinuxFactory () elif platform == "darwin" : factory = MacOSFactory () elif platform == "win32" : factory = WindowsFactory () else : raise NotImplementedError ( f "Не реализовано для вашей платформа: { платформа } " )кнопка = завод . create_button () результат = кнопка . краска () печать ( результат )
Альтернативная реализация с использованием самих классов как фабрик:
from abc import ABC , abstractmethod from sys import platform Кнопка класса ( ABC ): @abstractmethod def paint ( self ): passclass LinuxButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле Linux»class WindowsButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле Windows»class MacOSButton ( Button ): def paint ( self ): return «Визуализировать кнопку в стиле MacOS»if platform == "linux" : factory = LinuxButton elif platform == "darwin" : factory = MacOSButton elif platform == "win32" : factory = WindowsButton else : raise NotImplementedError ( f "Не реализовано для вашей платформы: { platform } " )button = factory () результат = кнопка . краска () печать ( результат )
См. Также [ править ]
- Бетонный класс
- Шаблон заводского метода
- Создание объекта
- Шаблон проектирования программного обеспечения
Ссылки [ править ]
- ^ a b Фриман, Эрик; Робсон, Элизабет; Сьерра, Кэти; Бейтс, Берт (2004). Хендриксон, Майк; Лукидес, Майк (ред.). Head First Design Patterns (мягкая обложка) . 1 . О'РЕЙЛИ. п. 156. ISBN. 978-0-596-00712-6. Проверено 12 сентября 2012 .
- ^ a b Фриман, Эрик; Робсон, Элизабет; Сьерра, Кэти; Бейтс, Берт (2004). Хендриксон, Майк; Лукидес, Майк (ред.). Head First Design Patterns (мягкая обложка) . 1 . О'РЕЙЛИ. п. 162. ISBN. 978-0-596-00712-6. Проверено 12 сентября 2012 .
- ↑ Эрих Гамма; Ричард Хелм; Ральф Джонсон; Джон Влиссидес (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. С. 87 и далее . ISBN 0-201-63361-2.
- ^ "Шаблон проектирования абстрактной фабрики - проблема, решение и применимость" . w3sDesign.com . Проверено 11 августа 2017 .
- ^ Гамма, Эрих; Ричард Хелм; Ральф Джонсон; Джон М. Влиссидес (2009-10-23). «Паттерны дизайна: абстрактная фабрика» . informIT. Архивировано из оригинала на 2009-10-23 . Проверено 16 мая 2012 .
Создание объекта: Абстрактная фабрика: Цель: предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.
- ^ Veeneman, Дэвид (2009-10-23). «Объектный дизайн для недоумевших» . Кодовый проект. Архивировано из оригинала на 2011-09-18 . Проверено 16 мая 2012 .
Фабрика изолирует клиента от изменений продукта или того, как он создается, и может обеспечить эту изоляцию между объектами, производными от самых разных абстрактных интерфейсов.
- ^ a b «Абстрактная фабрика: реализация» . OODesign.com . Проверено 16 мая 2012 .
- ^ "Шаблон проектирования абстрактной фабрики - структура и сотрудничество" . w3sDesign.com . Проверено 12 августа 2017 .
Внешние ссылки [ править ]
В Wikibook Computer Science Design Patterns есть страница по теме: Абстрактная фабрика в действии |
- Реализация абстрактной фабрики на Java
- СМИ, связанные с абстрактной фабрикой на Викискладе?
- Абстрактная фабричная диаграмма UML + формальная спецификация в LePUS3 и Class-Z (язык описания дизайна)
- Абстрактная фабрика Пример реализации абстрактной фабрики