namespace Ch4PizzaStore; public abstract class Pizza(string name) { public string Name { get; internal set; } = name; public IDough? Dough { get; internal set; } = null; public ISauce? Sauce { get; internal set; } = null; public IVeggies[]? VeggiesArray { get; internal set; } = null; public ICheese? Cheese { get; internal set; } = null; public IPepperoni? Pepperoni { get; internal set; } = null; public IClams? Clams { get; internal set; } = null; internal abstract void Prepare(); // While in Java all methods are by default `virtual`, C# is the same as C++, // all methods are final/selaed until explicitly marked as virtual. internal virtual void Bake() { Console.WriteLine("Bake for 25 minutes at 350"); } internal virtual void Cut() { Console.WriteLine("Cutting the pizza into diagonal slices"); } internal virtual void Box() { Console.WriteLine("Place pizza in official PizzaStore box"); } public override string ToString() { return "Pizza!"; // TODO: code to print the pizza here } } public class CheesePizza(IPizzaIngredientFactory ingredientFactory, string name) : Pizza(name) { internal override void Prepare() { Console.WriteLine($"Preparing {Name}"); Dough = ingredientFactory.CreateDough(); Sauce = ingredientFactory.CreateSauce(); Cheese = ingredientFactory.CreateCheese(); } } public class ClamPizza(IPizzaIngredientFactory ingredientFactory, string name) : Pizza(name) { internal override void Prepare() { Console.WriteLine($"Preparing {Name}"); Dough = ingredientFactory.CreateDough(); Sauce = ingredientFactory.CreateSauce(); Cheese = ingredientFactory.CreateCheese(); Clams = ingredientFactory.CreateClams(); } } public abstract class PizzaStore { protected abstract Pizza CreatePizza(string type); public Pizza OrderPizza(string type) { var pizza = CreatePizza(type); pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); return pizza; } } public class NYPizzaStore : PizzaStore { protected override Pizza CreatePizza(string type) { var ingredientFactory = new NYPizzaIngredientFactory(); return type switch { "cheese" => new CheesePizza(ingredientFactory, "New York Style Cheese Pizza"), "clam" => new ClamPizza(ingredientFactory, "New York Style Clam Pizza"), _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) }; } } public interface IDough; public interface ISauce; public interface ICheese; public interface IVeggies; public interface IPepperoni; public interface IClams; public interface IPizzaIngredientFactory { public IDough CreateDough(); public ISauce CreateSauce(); public ICheese CreateCheese(); public IVeggies[] CreateVeggies(); public IPepperoni CreatePepperoni(); public IClams CreateClams(); } public class ThinCrustDough : IDough; public class MarinaraSauce : ISauce; public class ReggianoCheese : ICheese; public class Garlic : IVeggies; public class Onion : IVeggies; public class Mushroom : IVeggies; public class RedPepper : IVeggies; public class SlicedPepperoni : IPepperoni; public class FreshClams : IClams; public class NYPizzaIngredientFactory : IPizzaIngredientFactory { public IDough CreateDough() { return new ThinCrustDough(); } public ISauce CreateSauce() { return new MarinaraSauce(); } public ICheese CreateCheese() { return new ReggianoCheese(); } public IVeggies[] CreateVeggies() { return [new Garlic(), new Onion(), new Mushroom(), new RedPepper()]; } public IPepperoni CreatePepperoni() { return new SlicedPepperoni(); } public IClams CreateClams() { return new FreshClams(); } }