Абстрактный заводской образец - Abstract factory pattern

Диаграмма классов UML

В абстрактная фабрика шаблон предоставляет способ инкапсулировать группу отдельных фабрики которые имеют общую тему без указания их конкретных классов.[1] При нормальном использовании клиентское программное обеспечение создает конкретную реализацию абстрактной фабрики, а затем использует общий интерфейс завода по созданию бетона объекты которые являются частью темы. В клиент не знает (или не заботится), какие конкретные объекты получает от каждой из этих внутренних фабрик, поскольку использует только общие интерфейсы их продуктов.[1] Этот шаблон отделяет детали реализации набора объектов от их общего использования и полагается на композицию объектов, поскольку создание объекта реализуется в методах, представленных в интерфейсе фабрики.[2]

Примером этого может быть абстрактный фабричный класс DocumentCreator который предоставляет интерфейсы для создания ряда продуктов (например, createLetter () и createResume ()). Система будет иметь любое количество производных конкретных версий DocumentCreator класс как FancyDocumentCreator или же СовременныйДокументСоздатель, каждый с другой реализацией createLetter () и createResume () что создаст соответствующий объект подобно FancyLetter или же ModernResume. Каждый из этих продуктов является производным от простого абстрактный класс подобно Письмо или же Продолжить из которых клиент знает. Клиентский код получит соответствующий пример из DocumentCreator и назовите его фабричные методы. Каждый из результирующих объектов будет создан из одного и того же DocumentCreator реализация и будет иметь общую тему (все они будут модными или современными объектами). Клиенту нужно только знать, как обращаться с абстрактным Письмо или же Продолжить класс, а не конкретная версия, которую он получил от бетонного завода.

А фабрика расположение конкретного класса в коде, в котором объекты построены. Цель использования шаблона - изолировать создание объектов от их использования и создать семейства связанных объектов без необходимости зависеть от их конкретных классов.[2] Это позволяет новым производные типы быть введенным без изменения кода, который использует базовый класс.

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

Обзор

Абстрактная фабрика [3]шаблон дизайна - один из двадцати трех хорошо известных Шаблоны проектирования GoF которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить, протестировать и повторно использовать.

Шаблон проектирования Абстрактная фабрика решает такие проблемы, как: [4]

  • Как приложение может быть независимым от того, как создаются его объекты?
  • Как класс может быть независимым от того, как создаются требуемые ему объекты?
  • Как можно создать семейства связанных или зависимых объектов?

Создание объектов непосредственно внутри класса, которому требуются объекты, является негибким, потому что оно передает класс конкретным объектам и делает невозможным изменение экземпляра позже независимо от (без изменения) класса. Это препятствует повторному использованию класса, если другие объекты являются требуется, и это затрудняет тестирование класса, потому что реальные объекты не могут быть заменены фиктивными объектами.

Шаблон проектирования Абстрактная фабрика описывает, как решать такие проблемы:

  • Инкапсулируйте создание объекта в отдельный (фабричный) объект. То есть определите интерфейс (AbstractFactory) для создания объектов и реализуйте интерфейс.
  • Класс делегирует создание объекта объекту-фабрике, а не создает объекты напрямую.

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

Определение

Суть абстрактного шаблона фабрики заключается в том, чтобы «предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов».[5]

использование

В фабрика определяет фактический конкретный тип объект должен быть создан, и именно здесь фактически создается объект (в C ++, например, новый оператор ). Однако фабрика возвращает только Абстрактные указатель к созданному бетонный объект.

Это изолирует клиентский код от создание объекта попросив клиентов спросить фабричный объект создать объект желаемого абстрактный тип и вернуть абстрактный указатель на объект.[6]

Поскольку фабрика возвращает только абстрактный указатель, клиентский код (который запросил объект у фабрики) не знает - и не обременен - ​​фактическим конкретным типом только что созданного объекта. Однако абстрактной фабрике известен тип конкретного объекта (и, следовательно, конкретной фабрики); например, фабрика может прочитать его из файла конфигурации. Клиенту не нужно указывать тип, так как он уже указан в конфигурационном файле. В частности, это означает:

  • Клиентский код ничего не знает о конкретном тип, не нужно включать файлы заголовков или же учебный класс декларации связанные с этим. Клиентский код имеет дело только с абстрактным типом. Объекты конкретного типа действительно создаются фабрикой, но клиентский код обращается к таким объектам только через их абстрактный интерфейс.[7]
  • Добавление новых конкретных типов осуществляется путем изменения клиентского кода для использования другой фабрики, обычно это одна строка в одном файле. Затем другая фабрика создает объекты разные конкретный тип, но по-прежнему возвращает указатель на одно и тоже абстрактный тип, как и раньше - таким образом изолируя клиентский код от изменений. Это значительно проще, чем изменять клиентский код для создания экземпляра нового типа, что потребовало бы изменения каждый место в коде, где создается новый объект (а также обеспечение того, чтобы все такие места кода также знали новый конкретный тип, включая, например, файл заголовка конкретного класса). Если все фабричные объекты хранятся глобально в одиночка объект, и весь клиентский код проходит через синглтон для доступа к надлежащей фабрике для создания объекта, тогда изменение фабрик так же просто, как изменение синглтон-объекта.[7]

Структура

Диаграмма UML

Пример диаграммы классов Метод createButton в интерфейсе GUIFactory возвращает объекты типа Button. Какая реализация Button будет возвращена, зависит от того, какая реализация GUIFactory обрабатывает вызов метода.
Пример диаграммы классовМетод createButton на GUIFactory интерфейс возвращает объекты типа Кнопка. Какая реализация Кнопка возвращается, зависит от того, какая реализация GUIFactory обрабатывает вызов метода.
Пример класса UML и диаграммы последовательности для шаблона проектирования Абстрактная фабрика. [8]
Пример класса UML и диаграммы последовательности для шаблона проектирования Абстрактная фабрика.[8]

В приведенном выше UML диаграмма классов, то Клиент класс, который требует ПродуктA и ПродуктB объекты не создают экземпляр ПродуктA1 и ПродуктB1 классы напрямую. Клиент относится к АннотацияФабрика интерфейс для создания объектов, что делает Клиент независимо от того, как создаются объекты (какие конкретные классы создаются). Завод1 класс реализует АннотацияФабрика интерфейс путем создания экземпляра ПродуктA1 и ПродуктB1 классы.
В UML схема последовательности показывает взаимодействия во время выполнения: Клиент вызовы объектов createProductA () на Завод1 объект, который создает и возвращает ПродуктA1 объект. Клиент звонки createProductB () на Завод1, который создает и возвращает ПродуктB1 объект.

Диаграмма Lepus3

Python пример

из abc импорт ABC, абстрактный методиз sys импорт Платформаучебный класс Кнопка(ABC):    @abstractmethod    def краска(себя):        проходитьучебный класс LinuxButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле Linux»учебный класс WindowsButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле Windows»учебный класс MacOSButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле MacOS»учебный класс GUIFactory(ABC):    @abstractmethod    def create_button(себя):        проходитьучебный класс LinuxFactory(GUIFactory):    def create_button(себя):        возвращаться LinuxButton()учебный класс WindowsFactory(GUIFactory):    def create_button(себя):        возвращаться WindowsButton()учебный класс MacOSFactory(GUIFactory):    def create_button(себя):        возвращаться MacOSButton()если Платформа == "Linux":    фабрика = LinuxFactory()Элиф Платформа == "Дарвин":    фабрика = MacOSFactory()Элиф Платформа == "win32":    фабрика = WindowsFactory()еще:    поднимать NotImplementedError(ж"Не реализовано для вашей платформы: {Платформа}")кнопка = фабрика.create_button()результат = кнопка.краска()Распечатать(результат)

Альтернативная реализация с использованием самих классов как фабрик:

из abc импорт ABC, абстрактный методиз sys импорт Платформаучебный класс Кнопка(ABC):    @abstractmethod    def краска(себя):        проходитьучебный класс LinuxButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле Linux»учебный класс WindowsButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле Windows»учебный класс MacOSButton(Кнопка):    def краска(себя):        возвращаться «Визуализировать кнопку в стиле MacOS»если Платформа == "Linux":    фабрика = LinuxButtonЭлиф Платформа == "Дарвин":    фабрика = MacOSButtonЭлиф Платформа == "win32":    фабрика = WindowsButtonеще:    поднимать NotImplementedError(ж"Не реализовано для вашей платформы: {Платформа}")кнопка = фабрика()результат = кнопка.краска()Распечатать(результат)

Смотрите также

Рекомендации

  1. ^ а б Фриман, Эрик; Робсон, Элизабет; Сьерра, Кэти; Бейтс, Берт (2004). Хендриксон, Майк; Лукидес, Майк (ред.). Шаблоны проектирования Head First (мягкая обложка). 1. О'РЕЙЛИ. п. 156. ISBN  978-0-596-00712-6. Получено 2012-09-12.
  2. ^ а б Фриман, Эрик; Робсон, Элизабет; Сьерра, Кэти; Бейтс, Берт (2004). Хендриксон, Майк; Лукидес, Майк (ред.). Шаблоны проектирования Head First (мягкая обложка). 1. О'РЕЙЛИ. п. 162. ISBN  978-0-596-00712-6. Получено 2012-09-12.
  3. ^ Эрих Гамма; Ричард Хелм; Ральф Джонсон; Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон Уэсли. стр.87ff. ISBN  0-201-63361-2.
  4. ^ "Шаблон проектирования Абстрактная фабрика - проблема, решение и применимость". w3sDesign.com. Получено 2017-08-11.
  5. ^ Гамма, Эрих; Ричард Хелм; Ральф Джонсон; Джон М. Влиссидес (2009-10-23). «Паттерны дизайна: абстрактная фабрика». informIT. Архивировано из оригинал на 2009-10-23. Получено 2012-05-16. Создание объекта: Абстрактная фабрика: Цель: предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.
  6. ^ Винеман, Дэвид (2009-10-23). «Объектный дизайн для недоумевших». Кодовый проект. Архивировано из оригинал на 2011-09-18. Получено 2012-05-16. Фабрика изолирует клиента от изменений продукта или того, как он создается, и может обеспечить эту изоляцию между объектами, производными от самых разных абстрактных интерфейсов.
  7. ^ а б «Абстрактная фабрика: реализация». OODesign.com. Получено 2012-05-16.
  8. ^ "Шаблон проектирования" Абстрактная фабрика "- структура и взаимодействие". w3sDesign.com. Получено 2017-08-12.

внешняя ссылка