Фабричный метод (шаблон проектирования)
| Информатика | Это незавершённая статья по информатике. Вы можете помочь проекту, исправив и дополнив её. |
Фабричный метод (англ. Factory Method) — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс инстанциировать. Иными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне. Также известен под названием виртуальный конструктор.
Цель
Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанциировать. Фабричный метод позволяет классу делегировать создание подклассам. Используется, когда:
- классу заранее неизвестно, объекты каких подклассов ему нужно создавать.
- класс спроектирован так, чтобы объекты, которые он создаёт, специфицировались подклассами.
- класс делегирует свои обязанности одному из нескольких вспомогательных подклассов, и планируется локализовать знание о том, какой класс принимает эти обязанности на себя.
Структура
Фабричный метод (Factory Method)
- Product - продукт
- определяет интерфейс объектов, создаваемых абстрактным методом;
- ConcreteProduct - конкретный продукт
- реализует интерфейс Product;
- Creator - создатель
- объявляет фабричный метод, который возвращает объект типа Product. Может также содержать реализацию этого метода "по умолчанию";
- может вызывать фабричный метод для создания объекта типа Product;
- ConcreteCreator - конкретный создатель
- переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.
Плюсы
- позволяет сделать код создания объектов более универсальным, не привязываясь к конкретным классам (ConcreteProduct), а оперируя лишь общим интерфейсом (Product);
- позволяет установить связь между параллельными иерархиями классов.
Минусы
- необходимость создавать наследника Creator для каждого нового типа продукта (ConcreteProduct).
Примеры
Java
<source lang="java">
public class FactoryMethodExample
{
public static void main(String[] args)
{
// an array of creators
Creator[] creators = new Creator[2];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();
// iterate over creators and create products
for (Creator creator: creators)
{
Product product = creator.factoryMethod();
System.out.printf("Created {%s}\n", product.getClass());
}
}
}
// Product
abstract class Product
{
}
// ConcreteProductA
class ConcreteProductA extends Product
{
}
// ConcreteProductB
class ConcreteProductB extends Product
{
}
// Creator
abstract class Creator
{
public abstract Product factoryMethod();
}
// У этого класса может быть любое кол-во наследников.
// Для создания нужного нам объекта можно написать следующие Фабрики: ConcreteCreatorA, ConcreteCreatorB
// ConcreteCreatorA
class ConcreteCreatorA extends Creator
{
@Override
public Product factoryMethod()
{
return new ConcreteProductA();
}
}
// ConcreteCreatorB
class ConcreteCreatorB extends Creator
{
@Override
public Product factoryMethod()
{
return new ConcreteProductB();
}
}
</source>
Результат работы:
Created {class ConcreteProductA}
Created {class ConcreteProductB}
C++
<source lang="cpp">
- include<iostream>
- include<string>
using namespace std;
// "Product" class Product{ public: virtual string getName() = 0; };
// "ConcreteProductA" class ConcreteProductA : public Product{ public: string getName(){ return "ConcreteProductA"; } };
// "ConcreteProductB" class ConcreteProductB : public Product{ public: string getName(){ return "ConcreteProductB"; } };
// "Creator" class Creator{ public: virtual Product* FactoryMethod() = 0; };
// "ConcreteCreatorA" class ConcreteCreatorA : public Creator{ public: Product* FactoryMethod() { return new ConcreteProductA(); } };
// "ConcreteCreatorB" class ConcreteCreatorB : public Creator{ public: Product* FactoryMethod() { return new ConcreteProductB(); } };
int main(){ const int size = 2; // An array of creators Creator* creators[size];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();
// Iterate over creators and create products for(int i=0;i<size;i++){ Product* product = creators[i]->FactoryMethod(); cout<<product->getName()<<endl; delete product; }
int a; cin>>a;
for(int i=0;i<size;i++){ delete creators[i]; } return 0; } </source>
C#
<source lang="csharp">
// Factory Method pattern -- Structural example
using System;
class MainApp {
static void Main()
{
// An array of creators
Creator[] creators = new Creator[2];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();
// Iterate over creators and create products
foreach(Creator creator in creators)
{
Product product = creator.FactoryMethod();
Console.WriteLine("Created {0}",
product.GetType().Name);
}
// Wait for user Console.Read(); }
}
// "Product"
abstract class Product { }
// "ConcreteProductA"
class ConcreteProductA : Product { }
// "ConcreteProductB"
class ConcreteProductB : Product { }
// "Creator"
abstract class Creator {
public abstract Product FactoryMethod();
}
// "ConcreteCreatorA"
class ConcreteCreatorA : Creator {
public override Product FactoryMethod()
{
return new ConcreteProductA();
}
}
// "ConcreteCreatorB"
class ConcreteCreatorB : Creator {
public override Product FactoryMethod()
{
return new ConcreteProductB();
}
} </source>
JavaScript
<source lang="javascript"> // "интерфейс" Product function Product() {}
// ConcreteProduct (реализация Product) function ProductA() {} ProductA.prototype = new Product(); ProductA.prototype.constructor = ProductA;
function ProductB() {} ProductB.prototype = new Product(); ProductB.prototype.constructor = ProductB;
// "интерфейс" Creator function Creator() { this.factoryMethod = function() {}; }
// ConcreteCreator (реализация Creator) function CreatorA() { this.factoryMethod = function() { return new ProductA(); }; } CreatorA.prototype = new Creator(); CreatorA.prototype.constructor = CreatorA;
function CreatorB() { this.factoryMethod = function() { return new ProductB(); }; } CreatorB.prototype = new Creator(); CreatorB.prototype.constructor = CreatorB;
// использование: var creatorA = new CreatorA(); var creatorB = new CreatorB();
var productA1 = creatorA.factoryMethod(); var productA2 = creatorA.factoryMethod(); var productB1 = creatorB.factoryMethod(); </source>
PHP5
<source lang="php"> abstract class User{
function __construct($name){ $this->name = $name; }
function getName(){ return $this->name; }
// Permission methods function hasReadPermission(){ return true; }
function hasModifyPermission(){ return false; }
function hasDeletePermission(){ return false; }
// Customization methods function wantsFlashInterface(){ return true; }
protected $name = NULL; }
class GuestUser extends User { }
class CustomerUser extends User { function hasModifyPermission(){ return true; } }
class AdminUser extends User { function hasModifyPermission(){ return true; }
function hasDeletePermission(){ return true; }
function wantsFlashInterface(){ return false; } }
class UserFactory { private static $users = array("Andi"=>"admin", "Stig"=>"guest", "Derick"=>"customer");
static function Create($name){ if(!isset(self::$users[$name])){ // Error out because the user doesn't exist } switch(self::$users[$name]){ case "guest": return new GuestUser($name); case "customer": return new CustomerUser($name); case "admin": return new AdminUser($name); default: // Error out because the user kind doesn't exist } } }
function boolToStr($b){ if($b == true){ return "Yes\n"; } else{ return "No\n"; } }
function displayPermissions(User $obj){ print $obj->getName()."'s permissions:\n"; print "Read: ".boolToStr($obj->hasReadPermission()); print "Modify: ".boolToStr($obj->hasModifyPermission()); print "Delete: ".boolToStr($obj->hasDeletePermission()); } function displayRequirements(User $obj){ if ($obj->wantsFlashInterface()) { print $obj->getName()." requires Flash\n"; } }
$logins = array("Andi", "Stig", "Derick");
foreach($logins as $login){ displayPermissions(UserFactory::Create($login)); displayRequirements(UserFactory::Create($login)); } </source>
См. также
Литература
- Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1 (также ISBN 5-272-00355-1)
| порождающие шаблоны проектирования |
| абстрактная фабрика | строитель | фабричный метод | прототип | одиночка | отложенная инициализация |
bg:Метод Фабрика (шаблон)
ca:Factory method
de:Fabrikmethode
en:Factory method pattern
es:Factory Method (patrón de diseño)
fr:Fabrique (patron de conception)
he:תבנית Factory Method
it:Factory method
ja:Factory Method パターン
ko:팩토리 메서드 패턴
ml:ഫാക്ടറി മെത്തേഡ് പാറ്റേൺ
nl:Factory (ontwerppatroon)
pl:Metoda wytwórcza (wzorzec projektowy)
pt:Factory Method
th:แฟกทอรีเมธอดแพตเทิร์น
uk:Фабричний метод (шаблон проектування)
vi:Factory method pattern
zh:工厂方法
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....