Абстрактна фабрикаАбстра́ктна фа́брика (англ. Abstract Factory) — шаблон проєктування, що забезпечує інкапсуляцію окремих фабрик під єдиною схемою, упускаючи їхню деталізацію. Належить до класу твірних шаблонів. В типових випадках застосування, клієнтський код створює конкретну реалізацію абстрактної фабрики, а потім використовує загальний універсальний інтерфейс фабрики, для створення екземплярів об'єктів, які є частиною схеми. Клієнтський код не знає (або не бере до уваги), які саме конкретно об'єкти він отримує від цих фабрик, оскільки він використовує універсальний інтерфейс для їхнього створення. Шаблон розмежовує деталі реалізації множини об'єктів від їхнього загального використання в коді, оскільки створення об'єкта здійснюється за допомогою методів, що забезпечуються інтерфейсом фабрики.[1] ПризначенняПодає інтерфейс для утворення родин взаємозв'язаних або взаємозалежних об'єктів, не специфікуючи їхніх конкретних класів. ЗастосуванняСлід використовувати шаблон Абстрактна фабрика коли:
Структура
Переваги
Недоліки
Відносини
РеалізаціяC++Приклад реалізації мовою С++
#include <string>
#include <iostream>
using namespace std;
// Сімейство елементів
// Базовий клас для всіх іграшок
class Toy
{
protected:
string name;
public:
Toy(string name)
{
this->name = name;
}
};
// Конкретні реалізації
struct WoodenCat : public Toy
{
WoodenCat() : Toy("Wooden Cat") { cout << this->name << '\n'; }
};
struct TeddyCat : public Toy
{
TeddyCat() : Toy("Teddy Cat") { cout << this->name << '\n'; }
};
struct WoodenBear : public Toy
{
WoodenBear() : Toy("Wooden Bear") { cout << this->name << '\n'; }
};
struct TeddyBear : public Toy
{
TeddyBear() : Toy("Teddy Bear") { cout << this->name << '\n'; }
};
// Абстрактна Фабрика (Abstract Factory)
struct IToyFactory
{
virtual Toy * GetBear() = 0;
virtual Toy * GetCat() = 0;
};
// конкретна фабрика (concrete factory)
struct TeddyToysFactory : IToyFactory
{
virtual Toy * GetBear()
{
return new TeddyBear();
}
virtual Toy * GetCat()
{
return new TeddyCat();
}
};
// і ще одна конкретна фабрика
struct WoodenToysFactory : IToyFactory
{
virtual Toy * GetBear()
{
return new WoodenBear();
}
virtual Toy * GetCat()
{
return new WoodenCat();
}
};
// Client
void create(IToyFactory * toyFactory)
{
Toy * bear = toyFactory->GetBear();
Toy * cat = toyFactory->GetCat();
}
void main()
{
// Спочатку створимо «дерев'яну» фабрику
auto p1 = WoodenToysFactory();
auto p2 = TeddyToysFactory();
create(&p1);
// А тепер створимо «плюшеву» фабрику,
create(&p2);
}
SwiftПриклад реалізації на мові Swift
Протоколprotocol Decimal {
func stringValue() -> String
// factory
static func make(string : String) -> Decimal
}
typealias NumberFactory = (String) -> Decimal
// Number implementations with factory methods
struct NextStepNumber : Decimal {
private var nextStepNumber : NSNumber
func stringValue() -> String { return nextStepNumber.stringValue }
// factory
static func make(string : String) -> Decimal {
return NextStepNumber(nextStepNumber:NSNumber(longLong:(string as NSString).longLongValue))
}
}
struct SwiftNumber : Decimal {
private var swiftInt : Int
func stringValue() -> String { return "\(swiftInt)" }
// factory
static func make(string : String) -> Decimal {
return SwiftNumber(swiftInt:(string as NSString).integerValue)
}
}
Абстрактна фабрикаenum NumberType {
case NextStep, Swift
}
class NumberHelper {
class func factoryFor(type : NumberType) -> NumberFactory {
switch type {
case .NextStep:
return NextStepNumber.make
case .Swift:
return SwiftNumber.make
}
}
}
Використанняlet factoryOne = NumberHelper.factoryFor(.NextStep)
let numberOne = factoryOne("1")
numberOne.stringValue()
let factoryTwo = NumberHelper.factoryFor(.Swift)
let numberTwo = factoryTwo("2")
numberTwo.stringValue()
PHPПриклад реалізації на мові PHP
<?php
// Загальний Інтерфейс реалізації
interface GuiFactoryInterface
{
public function buildButton(): ButtonInterface;
public function buildCheckBox(): CheckBoxInterface;
}
interface ButtonInterface
{
public function draw();
}
interface CheckBoxInterface
{
public function draw();
}
// Кінцева реалізація
class ButtonBootstrap implements ButtonInterface
{
public function draw() {return __CLASS__;}
}
class CheckBoxBootstrap implements CheckBoxInterface
{
public function draw() {return __CLASS__;}
}
class ButtonSemanticUI implements ButtonInterface
{
public function draw() {return __CLASS__;}
}
class CheckBoxSemanticUI implements CheckBoxInterface
{
public function draw() {return __CLASS__;}
}
// Інтерфейси для зв'язку однопитності
class BootstrapFactory implements GuiFactoryInterface
{
public function buildButton(): ButtonInterface
{
return new ButtonBootstrap();
}
public function buildCheckBox(): CheckBoxInterface
{
return new CheckBoxBootstrap();
}
}
class SemanticUIFactory implements GuiFactoryInterface
{
public function buildButton(): ButtonInterface
{
return new ButtonSemanticUI();
}
public function buildCheckBox(): CheckBoxInterface
{
return new CheckBoxSemanticUI();
}
}
class GuiKitFactory
{
public function getFactory($type): GuiFactoryInterface
{
switch ($type) {
case 'bootstrap':
$factory = new BootstrapFactory();
break;
case 'semantic_ui':
$factory = new SemanticUIFactory();
break;
default:
throw new Exception('Невідомий тип фабрики [' . $type . ']');
}
return $factory;
}
}
class CreationPatternController
{
private $guiKit;
public function __construct()
{
$this->guiKit = (new GuiKitFactory())->getFactory('bootstrap');
// OR
//$this->guiKit = (new GuiKitFactory())->getFactory('semantic_ui');
}
function AbstractFactory()
{
$result[] = $this->guiKit->buildCheckbox()->draw();
$result[] = $this->guiKit->buildButton()->draw();
return $result;
}
}
$drawer = new CreationPatternController();
$drawer->AbstractFactory();
Примітки
Джерела
Примітки
ЛітератураАлан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5.
|