Описание шаблона проектирования Абстрактная фабрика.
Описание шаблона Абстрактная фабрика
Порождающий шаблон проектирования Абстрактная фабрика применяется для создания семейств взаимосвязанных или взаимозависимых объектов без привязки к конкретным классам.
Пояснить работу шаблона проще на примере. Давайте я попробую.
Согласитесь, достаточно часто встречается ситуация, когда от текущего состояния приложения зависит его пользовательский интерфейс или отображаемые данные. На это состояние может влиять тип операционной системы, права пользователя, формат отображаемых данных и т.п. Получается, необходим то один набор компонентов, то другой. При этом компоненты приложения, как правило, должны взаимодействовать друг с другом, т.е. налицо ограничение на взаимодействие строго определенных компонентов. В этом случае, для создания набора определенных компонентов нам может помочь шаблон проектирования Абстрактная фабрика.
Пока на этом достаточно, остальное проще пояснить после приведения кода шаблона. Единственное, уточним смысл используемых терминов. Поскольку речь идет о фабрике, условимся, что ею создается какой-то продукт, под которым подразумевается программный объект, представляющий некую сущность реального мира.
Пример шаблона Абстрактная фабрика
Идея шаблона следующая – создаются две различные иерархии классов – продуктов и фабрик по их созданию. Первая определяет поведение и свойства нужных нам продуктов, а вторая служит для создания набора конкретных взаимосвязанных продуктов, подчеркиваю — взаимосвязанных. Интерфейс родителей этих иерархий при этом определяет общую функциональность наследников и позволяет избежать зависимости приложения от конкретных объектов.
Похоже не очень внятно, ничего, понять описанное поможет конкретный пример. Поэтому приступим. Вначале, как сказано выше, создадим интерфейс фабрик, который будет определять их поведение по производству продуктов, и классы, реализующие этот интерфейс. Вместо интерфейса можно объявить абстрактный класс, главное декларировать набор методов, которые будут определять интерфейс семейства фабрик.
interface Factory {
public function createProductA();
public function createProductB();
}
Наши фабрики, реализующие этот набор методов должны будут создавать два вида продуктов ProductA и ProductB
.
class BrandOneFactory implements Factory
{
public function createProductA()
{
return new BrandOneProductA();
}
public function createProductB()
{
return new BrandOneProductB();
}
}
class BrandTwoFactory implements Factory
{
public function createProductA()
{
return new BrandTwoProductA();
}
public function createProductB()
{
return new BrandTwoProductB();
}
}
Фабрики по созданию объектов определены, они готовы создавать два семейства взаимосвязанных продуктов. Теперь создаем иерархию продуктов. Метода та же: создаем интерфейс с набором методов и свойств будущих объектов и классы продуктов, реализующие этот интерфейс.
interface Product {
public getCaption();
public getPrice();
}
Class BrandOneProductA implements Product
{
public function getCaption()
{
}
public function getPrice()
{
}
}
Class BrandOneProductB implements Product
{
public function getCaption()
{
}
public function getPrice()
{
}
}
Class BrandTwoProductA implements Product
{
public function getCaption()
{
}
public function getPrice()
{
}
}
Class BrandTwoProductB implements Product
{
public function getCaption()
{
}
public function getPrice()
{
}
}
Классы взаимосвязанных продуктов созданы.
Теперь для получения семейства продуктов одного из производителей, мы должны создать объект нужного производителя, например, BrandOneFactory, и с его помощью получить нужный нам набор объектов.
В теории может быть хорошо и понятно, но достаточно абстрактно, а как это все использовать в приложении? Узнать об этом и даже скачать код действующего примера можно в записи Пример использования шаблона Абстрактная фабрика.
Если после этого нам в приложении понадобятся продукты еще одного бренда, мы создадим классы продуктов этого бренда, реализовав в нем интерфейс Product, и создадим класс фабрики для продукции нового бренда, который будет возвращать семейство конкретных продуктов.
При необходимости расширить функциональность продуктов мы можем создать еще один интерфейс и реализовать его
наследниках существующих продуктов. Все это будет происходить во вновь создаваемом коде, код же приложения при
этом практически не изменяется.
Достоинства.
Позволяет приложению создавать семейства взаимосвязанных объектов, без привязки к конкретным классам.
Создает строго определенный набор объектов, исключающий одновременное создание объектов других семейств.
Недостатки.
Сложно вводить новый тип продуктов, если его интерфейс не вписывается в существующий набор функций продукта.
Вернуться к списку шаблонов проектирования можно по ссылке.