Фабричний метод (шаблон проєктування)Фабричний метод (англ. Factory Method) — шаблон проєктування, належить до класу твірних шаблонів. ПризначенняВизначає інтерфейс для створення об'єкта, але залишає підкласам рішення про те, який саме клас інстанціювати. Фабричний метод дозволяє класу делегувати інстанціювання підкласам. ЗастосуванняСлід використовувати шаблон Фабричний метод коли:
Структура![]()
Переваги
Недоліки
СтосункиТворець покладається на свої підкласи в означенні фабричного методу, котрий буде повертати екземпляр відповідного конкретного продукту. РеалізаціяДеякі з сучасних мов програмування підтримують фабричний метод на рівні власних конструкцій таким чином, що ієрархія класів «Creator» не реалізовується. Дивись альтернативні реалізації нижче. PythonРеалізація мовою Python
#coding: utf-8
class Culture:
def __repr__(self):
return self.__str__()
class Democracy(Culture):
def __str__(self):
return 'Democracy'
class Dictatorship(Culture):
def __str__(self):
return 'Dictatorship'
class Government:
culture = ''
def __str__(self):
return self.culture.__str__()
def __repr__(self):
return self.culture.__repr__()
def set_culture(self):
raise AttributeError('Not Implemented Culture')
class GovernmentA(Government):
def set_culture(self):
self.culture = Democracy()
class GovernmentB(Government):
def set_culture(self):
self.culture = Dictatorship()
g1 = GovernmentA()
g1.set_culture()
print (str(g1))
g2 = GovernmentB()
g2.set_culture()
print (str(g2))
JavaРеалізація мовою Java
abstract class Product { }
class ConcreteProductA extends Product { }
class ConcreteProductB extends Product { }
abstract class Creator {
public abstract Product factoryMethod();
}
class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() { return new ConcreteProductA(); }
}
class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() { return new ConcreteProductB(); }
}
public class FactoryMethodExample {
public static void main(String[] args) {
// an array of creators
Creator[] creators = {new ConcreteCreatorA(), new ConcreteCreatorB()};
// iterate over creators and create products
for (Creator creator: creators) {
Product product = creator.factoryMethod();
System.out.printf("Created {%s}\n", product.getClass());
}
}
}
Результат роботи:
C++Реалізація мовою C++
#include <iostream>
#include <string>
using namespace std;
class Product
{
public:
virtual string getName() = 0;
virtual ~Product(){}
};
class ConcreteProductA: public Product
{
public:
string getName() { return "ConcreteProductA"; }
};
class ConcreteProductB : public Product
{
public:
string getName() { return "ConcreteProductB"; }
};
class Creator
{
public:
virtual Product* factoryMethod() = 0;
};
class ConcreteCreatorA: public Creator
{
public:
Product* factoryMethod()
{
return new ConcreteProductA();
}
};
class ConcreteCreatorB : public Creator
{
public:
Product* factoryMethod()
{
return new ConcreteProductB();
}
};
int main()
{
static const size_t count = 2;
ConcreteCreatorA CreatorA;
ConcreteCreatorB CreatorB;
// An array of creators
Creator* creators[count] = {&CreatorA,&CreatorB};
// Iterate over creators and create products
for (size_t i = 0; i < count; i++) {
Product* product = creators[i]->factoryMethod();
cout << product->getName() << endl;
delete product;
}
return 0;
}
C#Реалізація мовою C#
using System;
using System.Collections.Generic;
namespace Factory
{
abstract class Product { }
class ConcreteProductA : Product { }
class ConcreteProductB : Product { }
abstract class Creator{
public abstract Product FactoryMethod();
}
class ConcreteCreatorA : Creator{
public override Product FactoryMethod( ){ return new ConcreteProductA(); }
}
class ConcreteCreatorB : Creator{
public override Product FactoryMethod() { return new ConcreteProductB(); }
}
public class MainApp
{
public static void Main()
{
// an array of creators
Creator[] creators = {new ConcreteCreatorA(), new ConcreteCreatorB()};
// iterate over creators and create products
foreach (Creator creator in creators){
Product product = creator.FactoryMethod();
Console.WriteLine("Created {0}", product.GetType());
}
// Wait for user
Console.Read();
}
}
}
Реалізація мовою C#
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
namespace FactoryMethod
{
// ускладнимо архітектуру
// але забезпечимо повну незалежність класів у ієрархії
// створює продукт
public interface ICreator<out TReturnValue>
{
TReturnValue Create();
}
// фабрика
// реєструє, створює продукт
public interface IFactory<in TKey, in TRegValue, out TReturnValue>
where TRegValue : ICreator<TReturnValue>
{
void Registrate(TKey key, TRegValue value);
void UnRegistrate(TKey key);
TReturnValue MakeInstance(TKey key);
}
// ініціалізатор фабрики
// наповнює фабрику початковими значеннями
public interface IFactoryInitializer<in TFactory>
{
void Initialize(TFactory factory);
}
// узагальнений клас фабрики,
public class FactoryBase<TKey, TReturnValue> : IFactory<TKey, ICreator<TReturnValue>, TReturnValue>
{
// FIELDS
IDictionary<TKey, ICreator<TReturnValue>> factory;
// CONSTRUCTORS
public FactoryBase()
{
factory = new ConcurrentDictionary<TKey, ICreator<TReturnValue>>();
}
// METHODS
public TReturnValue MakeInstance(TKey key)
{
// checks
if (key == null) throw new ArgumentNullException(nameof(key));
if (!factory.ContainsKey(key)) throw new InvalidOperationException($"No such key '{key}'");
// make instance
return factory[key].Create();
}
public void Registrate(TKey key, ICreator<TReturnValue> creator)
{
// checking argument
// key
if (key == null) throw new ArgumentNullException(nameof(key));
if (factory.ContainsKey(key)) throw new InvalidOperationException($"Type by key '{key}' has been already registered");
// value
if (creator == null) throw new ArgumentNullException(nameof(creator));
Type creatorType = creator.GetType();
if (creatorType.IsInterface || creatorType.IsAbstract) throw new ArgumentException(nameof(creator));
// adding
factory.Add(key, creator);
}
public void UnRegistrate(TKey key)
{
// checking argument
// key
if (key == null) throw new ArgumentNullException(nameof(key));
if (!factory.ContainsKey(key)) throw new InvalidOperationException($"No such key '{key}'");
// removing
factory.Remove(key);
}
}
// SHAPES
// ієрархія класів
abstract class ShapeBase { }
class Square : ShapeBase { }
class Circle : ShapeBase { }
class Rectangle : ShapeBase { }
// SHAPE CREATORS
// для кожного класу в ієрархії варто написати
// клас відповідальний за створення
// (в C# не обов'язково, можна використати Activator)
class SquareCreator : ICreator<Square>
{
public Square Create()
{
// можливо створення за допомогою
// будь-якого, можливо твірного, шаблону проєктування
return new Square();
}
}
class DefaultCreator<T> : ICreator<T> where T: new()
{
public T Create()
{
return new T();
}
}
class CircleCreator : DefaultCreator<Circle> { }
// використовується при реєстрації
// DefaultCreator<Rectangle>
// зменшує кількість класів Creator'ів
// та деколи краще мати окремі класи Creator'ів для кожного об'єкта
// так при потребі змінити спосіб створення об'єкта, доведеться змінити лише відповідний метод Create
// а не створювати новий клас, та шукати усі місця в яких він реєструється
// FACTORY
// конкретна фабрика
class ShapeFactory : FactoryBase<string, ShapeBase>
{
public ShapeFactory(IFactoryInitializer<ShapeFactory> factoryInitializer)
{
factoryInitializer.Initialize(this);
}
}
// конкретний ініціалізатор
class DefaultShapeFactoryInitializer : IFactoryInitializer<ShapeFactory>
{
public void Initialize(ShapeFactory factory)
{
factory.Registrate(nameof(Square), new SquareCreator());
factory.Registrate(nameof(Circle), new CircleCreator());
factory.Registrate(nameof(Rectangle), new DefaultCreator<Rectangle>());
}
}
class Program
{
static void Main(string[] args)
{
ShapeFactory factory = new ShapeFactory(new DefaultShapeFactoryInitializer());
string[] shapeToCreate = { nameof(Square), nameof(Circle) };
foreach (string item in shapeToCreate)
{
ShapeBase shape = factory.MakeInstance(item);
Console.WriteLine(shape.ToString());
}
Console.ReadLine();
}
}
}
JavaScriptРеалізація мовою JavaScript
function Product() {this.getName=null;}
'use strict';
// Інстанціювання функції
function ConcreteProductA() {
this.getName = function() {
// Повертання строки з вказаним змістом
return 'ConcreteProductA';
};
}
// Інстанціювання функції
function ConcreteProductB() {
this.getName = function() {
// Повертання строки з вказаним змістом
return 'ConcreteProductB';
};
}
// Інстанціювання функції
function ConcreteCreatorA() {
this.factoryMethod = function() {
// Повертання нової функції з рядка 7
return new ConcreteProductA();
};
}
// Інстанціювання функції
function ConcreteCreatorB() {
this.factoryMethod = function() {
// Повертання нової функції з рядка
return new ConcreteProductB();
};
}
// Створюємо масив функцій
const creators = [new ConcreteCreatorA(), new ConcreteCreatorB()];
creators.forEach((el) => {
console.log(el.factoryMethod().getName());
});
PHP5Код мовою PHP
<?php
interface Product{
public function GetName();
}
class ConcreteProductA implements Product{
public function GetName() { return "ProductA"; }
}
class ConcreteProductB implements Product{
public function GetName() { return "ProductB"; }
}
interface Creator{
public function FactoryMethod();
}
class ConcreteCreatorA implements Creator{
public function FactoryMethod() { return new ConcreteProductA(); }
}
class ConcreteCreatorB implements Creator{
public function FactoryMethod() { return new ConcreteProductB(); }
}
// An array of creators
$creators = array( new ConcreteCreatorA(), new ConcreteCreatorB() );
// Iterate over creators and create products
for($i = 0; $i < count($creators); $i++){
$products[] = $creators[$i]->FactoryMethod();
}
header("content-type:text/plain");
echo var_export($products);
?>
Код мовою PHP
<?php
abstract class Animal
{
// фабричний метод, на основі типу повертаємо об'єкт
public static function initial($animal)
{
return new $animal();
}
abstract public function voice();
}
class Lion extends Animal
{
public function voice()
{
echo 'Rrrrrrrr i\'m the lion <br />' . PHP_EOL;
}
}
class Cat extends Animal
{
public function voice()
{
echo 'Meow, meow i\'m the kitty <br />' . PHP_EOL;
}
}
$animal1 = Animal::initial('Lion');
$animal2 = Animal::initial('Cat');
$animal1->voice();
$animal2->voice();
Код мовою 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();
}
}
// Опис роботи з об'єктом
abstract class AbstractForm
{
public function render()
{
$guiKit = $this->createGuiKit();
$result[] = $guiKit->buildCheckBox()->draw();
$result[] = $guiKit->buildButton()->draw();
return $result;
}
abstract function createGuiKit(): GuiFactoryInterface;
}
class BootstrapDialogForm extends AbstractForm
{
public function createGuiKit(): GuiFactoryInterface
{
return new BootstrapFactory();
}
}
class SemanticUIDialogForm extends AbstractForm
{
public function createGuiKit(): GuiFactoryInterface
{
return new SemanticUIFactory();
}
}
function factoryMethod()
{
$dialogForm = new BootstrapDialogForm();
// OR
//$dialogForm = new SemanticUIDialogForm();
return $dialogForm->render();
}
$renderedDialogForm = factoryMethod();
DelphiРеалізація мовою Delphi
program FactoryMethod;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Product
TProduct = class(TObject)
public
function GetName: string; virtual; abstract;
end;
// ConcreteProductA
TConcreteProductA = class(TProduct)
public
function GetName: string; override;
end;
// ConcreteProductB
TConcreteProductB = class(TProduct)
public
function GetName: string; override;
end;
// Creator
TCreator = class(TObject)
public
function FactoryMethod: TProduct; virtual; abstract;
end;
// ConcreteCreatorA
TConcreteCreatorA = class(TCreator)
public
function FactoryMethod: TProduct; override;
end;
// ConcreteCreatorB
TConcreteCreatorB = class(TCreator)
public
function FactoryMethod: TProduct; override;
end;
{ ConcreteProductA }
function TConcreteProductA.GetName: string;
begin
Result := 'ConcreteProductA';
end;
{ ConcreteProductB }
function TConcreteProductB.GetName: string;
begin
Result := 'ConcreteProductB';
end;
{ ConcreteCreatorA }
function TConcreteCreatorA.FactoryMethod: TProduct;
begin
Result := TConcreteProductA.Create;
end;
{ ConcreteCreatorB }
function TConcreteCreatorB.FactoryMethod: TProduct;
begin
Result := TConcreteProductB.Create;
end;
const
Count = 2;
var
Creators: array[1..Count] of TCreator;
Product: TProduct;
I: Integer;
begin
// An array of creators
Creators[1] := TConcreteCreatorA.Create;
Creators[2] := TConcreteCreatorB.Create;
// Iterate over creators and create products
for I := 1 to Count do
begin
Product := Creators[I].FactoryMethod;
WriteLn(Product.GetName);
Product.Free;
end;
for I := 1 to Count do
Creators[I].Free;
ReadLn;
end.
Реалізація мовою Delphi (віртуальні конструктори)
program FactoryMethod;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Product
TProduct = class(TObject)
private
SubName : string;
public
function GetName: string; virtual; abstract;
function GetFullName: string;
constructor Create; virtual; abstract;
end;
TProductClass = class of TProduct;
// ConcreteProductA
TConcreteProductA = class(TProduct)
public
function GetName: string; override;
constructor Create; override;
end;
// ConcreteProductB
TConcreteProductB = class(TProduct)
public
function GetName: string; override;
constructor Create; override;
end;
{ TProduct}
function TProduct.GetFullName: string;
begin
Result := GetName + ' : ' + SubName;
end;
{ ConcreteProductA }
constructor TConcreteProductA.Create;
begin
inherited;
SubName := 'Product A subname';
end;
function TConcreteProductA.GetName: string;
begin
Result := 'ConcreteProductA';
end;
{ ConcreteProductB }
constructor TConcreteProductB.Create;
begin
inherited;
SubName := 'Product B subname';
end;
function TConcreteProductB.GetName: string;
begin
Result := 'ConcreteProductB';
end;
const
Count = 2;
var
Creators: array[1..Count] of TProductClass;
Product: TProduct;
I: Integer;
begin
// An array of creators
Creators[1] := TConcreteProductA;
Creators[2] := TConcreteProductB;
// Iterate over creators and create products
for I := 1 to Count do
begin
Product := Creators[I].Create;
WriteLn(Product.GetFullName);
Product.Free;
end;
ReadLn;
end.
Див. такожДжерела
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia