Один из самых популярных паттернов, позволяет создавать различные продукты, без указания классов продуктов.
Паттерн Фабричный Метод определяет интерфейс создания объекта, но позволяет субклассам выбрать класс создаваемого экземпляра. Таким образом, Фабричный Метод делегирует операцию создания экземпляра субклассам.
Давайте рассмотрим пример, который предполагает создания конвейера по изготовлению пиццы. Я не буду сильно перегружать кодом, остановимся на изготовлении одной конкретной пиццы, но с различной начинкой.
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Паттерн_Фабричный_метод { public abstract class PizzaStore { public Pizza OrderPizza(string name) { Pizza pizza; pizza = CreatePizza(name); pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); return pizza; } public abstract Pizza CreatePizza(string name); } public class ItaliaStylePizzaStore : PizzaStore { public override Pizza CreatePizza(string name) { Pizza pizza = null; switch (name) { case "сыр": return pizza = new ItaliaStyleCheesePizza(); case "пепперони": return pizza = new ItaliaStylePepperoniPizza(); case "вегетарианская": return pizza = new ItaliaStyleVeggiePizza(); default: return pizza; } } } public class ItaliaStyleCheesePizza : Pizza { public ItaliaStyleCheesePizza() { Name = "Итальянская пицца с соусом и сыром"; Dough = "Тесто на тонкой основе"; Sauce = "Специальны соус"; Console.WriteLine("Итальянская пицца с сыром"); } } public class ItaliaStylePepperoniPizza : Pizza { public ItaliaStylePepperoniPizza() { Console.WriteLine("Итальянская пицца с Пепперони"); } } public class ItaliaStyleVeggiePizza : Pizza { public ItaliaStyleVeggiePizza() { Console.WriteLine("Итальянская пицца с Вегетарианская"); } } public abstract class Pizza { public string Name { get; set; } public string Dough { get; set; } public string Sauce { get; set; } ArrayList toppings = new ArrayList(); internal void Prepare() { Console.WriteLine("Готовим пиццу"); Console.WriteLine("Готовим: " + Name); Console.WriteLine("Подбрасываем тесто: " + Dough); Console.WriteLine("Добавляем соус"); for (int i = 0; i < toppings.Count; i++) { Console.WriteLine(" " + toppings[i]); } } internal void Bake() { Console.WriteLine("Печем пиццу 25 минут"); } internal void Cut() { Console.WriteLine("Нарезаем пиццу по диагонали"); } internal void Box() { Console.WriteLine("Упаковываем пиццу в коробку"); } } public class CheesePizza : Pizza { public CheesePizza() { Console.WriteLine("-=Пицца с сыром=-"); } } public class PepperoniPizza : Pizza { public PepperoniPizza() { Console.WriteLine("-=Пицца Пепперони=-"); } } public class VeggiePizza : Pizza { public VeggiePizza() { Console.WriteLine("-=Пицца Вегетарианска=-"); } } public class SimplePizzaFactory { public Pizza CreatePizza(string name) { Pizza pizza = null; switch (name) { case "сыр": return pizza = new CheesePizza(); case "пепперони": return pizza = new PepperoniPizza(); case "вегетарианская": return pizza = new VeggiePizza(); default: return pizza; } } } class Program { static void Main(string[] args) { PizzaStore italiapizzaStore = new ItaliaStylePizzaStore(); Pizza pizza = italiapizzaStore.OrderPizza("сыр"); Console.ReadKey(); } } }
В данном примере мы могли использовать вместо абстрактного класса пиццы, интрефес, но тогда нам надо было бы создатвать новые классы по приготовлению пиццы, потому частичная реализации сделана в абстрактном классе пиццы.
