Przyrządzanie kawy składa się z kilku etapów : zaparzania, słodzenia i dodatków. Każdy z nich można przeprowadzić na różny sposób. Dodatkami mogą być mleko, śmietanka czy cynamon. Zamawiając kawę moglibyśmy za każdym razem podawać sposób parzenia i dodatki. Przeważnie jednak w menu mamy dostępne gotowe pozycje z opisanymi różnicami, które możemy zamówić.
Zastosowanie:
Wzorca konstruktora używamy przy tworzeniu złożonych obiektów. Skorzystanie z niego umożliwi oddzielenie logiki tworzenia obiektu, na którą składa się wiele etapów od konkretnych implementacji, gdzie za etapami idą konkretne dane. Zapewnia to reużywalnosć - ta sama logika jest w stanie stworzyć wiele obiektów. Warto pamiętać, że te obiekty różnią się danymi, a nie typami.
Zasada działania:
Stosuje się pewną hierarchię przy użyciu wzorca konstruktora. Klasa reżysera, z której API korzysta "reszta świata" ma za zadanie nadzorowanie całością. Przechowuje ona referencję do konkretnego buildera, wywołuje jego metody w odpowiedniej kolejności tak, aby stworzyć obiekt, a także udostępnia metodę, która zwraca instancję obiektu. Klasa abstrakcyjna buildera przechowuje referencję do produktu, udostępnia abstrakcyjne metody, które odpowiadają za etapy tworzenia produktu, a także metodę zwracającą instancję. Konkretne implementacje buildera nadpisują metody abstrakcyjne z klasy bazowej, gdzie zawarta jest konkretna logika przy tworzeniu produktu.
Przykład implementacyjny:
public class Pizza { public string Name { get; set; } public int DoughHeight { get; set; } public List<MeatType> MeatTypes { get; set; } public List<CheeseType> CheeseTypes { get; set; } public List<string> Vegetables { get; set; } } public enum MeatType { Salami, Bacon, Ham } public enum CheeseType { Parmesan, Edam, Gouda }
public abstract class PizzaBuilder { protected Pizza pizza; public Pizza GetPizza() { return pizza; } public void CreateNewPizza() { pizza = new Pizza(); } public abstract void SetName(); public abstract void MakeDough(); public abstract void PrepareCheese(); public abstract void PrepareMeat(); public abstract void PrepareVegetables(); }
public class NapoletanaPizzaBuilder : PizzaBuilder { public override void SetName() { pizza.Name = "Napoletana"; } public override void MakeDough() { pizza.DoughHeight = 10; } public override void PrepareCheese() { pizza.CheeseTypes = new List<CheeseType>(){CheeseType.Gouda}; } public override void PrepareMeat() { pizza.MeatTypes = new List<MeatType>() { MeatType.Salami }; } public override void PrepareVegetables() { pizza.Vegetables = new List<string>() { "Olives", "Paprika" }; } }
public class SpararePizzaBuilder : PizzaBuilder { public override void SetName() { pizza.Name = "Sparare"; } public override void MakeDough() { pizza.DoughHeight = 8; } public override void PrepareCheese() { pizza.CheeseTypes = new List<CheeseType>(){CheeseType.Edam}; } public override void PrepareMeat() { pizza.MeatTypes = new List<MeatType>(){MeatType.Bacon}; } public override void PrepareVegetables() { pizza.Vegetables = new List<string>() { "Mushrooms", "Onion", "Tomato", "Garlic" }; } }
public class PizzaDirector { private PizzaBuilder _builder; public PizzaDirector(PizzaBuilder builder) { _builder = builder; } public void CreatePizza() { _builder.CreateNewPizza(); _builder.SetName(); _builder.MakeDough(); _builder.PrepareCheese(); _builder.PrepareMeat(); _builder.PrepareVegetables(); } public Pizza GetPizza() { return _builder.GetPizza(); } }
class Program { static void Main(string[] args) { var maker = new PizzaDirector(new NapoletanaPizzaBuilder()); maker.CreatePizza(); Console.WriteLine(maker.GetPizza().Name); maker = new PizzaDirector(new SpararePizzaBuilder()); maker.CreatePizza(); Console.WriteLine(maker.GetPizza().Name); } }
Brak komentarzy:
Prześlij komentarz