Паттерн «абстрактная фабрика», в отличии от «шизофреника» паттерна «синглтон», вполне даже имеет аналогии в окружающем мире.
Главная цель: порождающий паттерн «абстрактная фабрика» служит для группового изменения поведения объектов, сохраняя при этом общий интерфейс.
Объясняющая аналогия из жизни, например, из зоопарка.
Представим, чтодолжен родиться детеныш, а Вы ветеринар, которому предстоит принять этого детеныша.
Вы вбегаете в комнату в момент самого рождения и узнаете кто именно из зверей в данное время решил разрешиться детенышем.
Снаружи репортеры ждут прибавления численности млекопитающих данного зоопарка.
По идее, мы знаем, что любой детеныш имеет конечности и рот, но если случится жеребенок, то его конечности и рот будут немного иначе использоваться, чем, например, лапы и рот тигренка.
Конечности и рот это и есть группа классов, которые наследуются от интерфейса.
Для Вас, как сотрудника зоопарка, которого разбудили ночью для выполнения своих обязанностей, абсолютно не важно кто появиться на свет:
главное — оно бегает и ест.
Вы и есть паттерн - абстрактная фабрика.
Пример кода php класса pattern abstract factory
/* вот наша абстрактная фабрика */ abstract class zooFactory {
будем считать, что этот статический класс и метод - enterRoom::whatSee() - существует и независимо от всей группы дает объективную картину. На его месте в коде может быть метод указания на операционную систему или используемый язык, или т.п.
/* точка входа в наш паттерн */
public static function getFactory() {
/* по нашему сценарию, вы вошли в комнату и увидели что-то */
if ( enterRoom::whatSee() == 'horse' ) {
return( new horseFactory() );
} else {
return( new tigerFactory() ); }
}
/* у наследованного класса должен быть метод создания рта */
public abstract function createMouth();
/* по идее мы еще затронули конечности, но опустим их */
// public abstract function createLegs();
}
/* класс лошадей */
class horseFactory
extends zooFactory {
/* обязательный метод создания рта */
public function createMouth() {
return( new horseMouth() ); }
}
/* класс тигров */
class tigerFactory
extends zooFactory {
/* обязательный метод создания рта */
public function createMouth() { return( new tigerMouth() ); }
}
/* в группу классов входит интерфейс ртов */
abstract class zooMouth {
/* у наследованного класса должен быть метод использования рта */
public abstract function useIt(); }
/* класс ртов лошади */
class horseMouth
extends zooMouth {
/* игогокаем */
public function useIt() {
echo 'EEEHHGGOOGOOO'; }
}
/* класс ртов тигра */
class tigerMouth
extends zooMouth {
/* рычим */
public function useIt() { echo 'HRRRRR'; }
}
// создаем существо, то есть входим в фабрику
$zooBeing = zooFactory::getFactory();
// создаем рот без понимания, что именно за существо
$mouth = $zooBeing->createMouth();
// используем рот - первый звук детеныша - !независимо от того, кто это!
$mouth->useIt();
При использовании паттерна образуется группа взаимосвязанных и взаимозависимых объектов, но мы изолируем конкретные классы наших детенышей, оставляя только точку входа.
Так же мы безболезненно можем расширять список видов детенышей, сохраняя интерфейс взаимодействия с инстанцируемыми объектами. Но, к сожалению, наша "абстрактная фабрика" не сможет "обслуживать" бабочек или инопланетян, так как они не смогут вписываться в интерфейс описанной группы млекопитающих.
Главным преимуществом можно считать независимость группы от деталей создания и компановки объектов. Главной задачей программиста становится взаимодействие с интерфейсами, но не их конкретными реализациями.
Взаимодействие происходит лишь отталкиваясь от интерфейса по схеме:
родился() —> открыл рот() -> издал звук()
Надеюсь, стало понятно, как использовать данный паттерн «абстрактная фабрика» .
Удачного кода!