Фабричный метод (шаблон проектирования)
Материал из Seo Wiki - Поисковая Оптимизация и Программирование
| Файл:LampFlowchart-ru.svg | Это незавершённая статья по информатике. Вы можете помочь проекту, исправив и дополнив её. |
Фабричный метод (англ. Factory Method) — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс инстанциировать. Иными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне. Также известен под названием виртуальный конструктор.
Содержание |
[править] Цель
Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанциировать. Фабричный метод позволяет классу делегировать создание подклассам. Используется, когда:
- классу заранее неизвестно, объекты каких подклассов ему нужно создавать.
- класс спроектирован так, чтобы объекты, которые он создаёт, специфицировались подклассами.
- класс делегирует свои обязанности одному из нескольких вспомогательных подклассов, и планируется локализовать знание о том, какой класс принимает эти обязанности на себя.
[править] Структура
- Product - продукт
- определяет интерфейс объектов, создаваемых абстрактным методом;
- ConcreteProduct - конкретный продукт
- реализует интерфейс Product;
- Creator - создатель
- объявляет фабричный метод, который возвращает объект типа Product. Может также содержать реализацию этого метода "по умолчанию";
- может вызывать фабричный метод для создания объекта типа Product;
- ConcreteCreator - конкретный создатель
- переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.
[править] Плюсы
- позволяет сделать код создания объектов более универсальным, не привязываясь к конкретным классам (ConcreteProduct), а оперируя лишь общим интерфейсом (Product);
- позволяет установить связь между параллельными иерархиями классов.
[править] Минусы
- необходимость создавать наследника Creator для каждого нового типа продукта (ConcreteProduct).
[править] Примеры
[править] 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(); } }
Результат работы:
Created {class ConcreteProductA}
Created {class ConcreteProductB}
[править] C++
# 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; }
[править] C#
// 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(); } }
[править] 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();
[править] PHP5
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)); }
[править] См. также
[править] Литература
- Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1 (также ISBN 5-272-00355-1)
| порождающие шаблоны проектирования |
| абстрактная фабрика | строитель | фабричный метод | прототип | одиночка | отложенная инициализация |
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:工厂方法