Паттерн Компоновщик на C# на примерах

Паттерн Компоновщик объединяет объекты в древовидные структуры для представления иерархий часть\целое. Компоновщик позволяет клиенту выполнять однородные операции сами отдельными объектами и их совокупностями.

Паттерн Компоновщик позволяет клиенту выполнять однородные операции с комбинациями и отдельными объектами.

Паттерн Компоновщик предоставляет структуру для хранения как отдельных объектов, так и комбинаций.

В реализации паттерна Компоновщик приходится искать баланс между прозрачностью, безопасностью и вашими потребностями.

Рассмотрим пример, в котором нам надо реализовать меню для интерактивного автомата в одной из кафешек.

У нас имеются отдельные классы завтрака и обеда, с набором каких-то блюд. Когда клиент подходит к автомату, он выбирает блюда для завтрака или обеда, но часто бывает такое что в обед могут входить блюда из завтрака. А также дополнятся новыми блюдами сегодняшнего дня. Представляете сложность иерархии построения такой логики программы, когда каждый день придется вносить еще какие-то правки? Вот тут и приходит к нам на помощь Паттерн Компоновщик, который поможет создать древовидное меню блюд, и выводить всю информацию о них.

using System;
using System.Collections;

namespace Паттерн_Компоновщик
{
    // Базовый класс Компонент объявляет общие операции как для простых, так и
    // для сложных объектов структуры.
    public abstract class MenuComponent
    {
        public virtual void Add(MenuComponent menuComponent)
        {
            throw new NotImplementedException();
        }
       
        public virtual void Remove(MenuComponent menu)
        {
            throw new NotImplementedException();
        }
        public virtual MenuComponent GetChild(int i)
        {
            throw new NotImplementedException();
        }

        public virtual double GetPrice()
        {
            throw new NotImplementedException();
        }
        public virtual bool IsVegetarian()
        {
            throw new NotImplementedException();
        }
        public virtual void Print()
        {
            throw new NotImplementedException();
        }
    }

    public class MenuItem:MenuComponent
    {
        public string Name { get; }
        public string Description { get; }
        public bool Vegetarian { get; }
        public double Price { get; }

        public MenuItem(string name, string description, bool vegetarian, double price)
        {
            this.Name = name;
            this.Description = description;
            this.Vegetarian = vegetarian;
            this.Price = price;
        }
        public override bool IsVegetarian()
        {
            return Vegetarian;
        }
        public override void Print()
        {
            Console.Write(" "+Name);
            if (IsVegetarian())
            {
                Console.Write("(v)");
            }
            Console.WriteLine(", "+Price);
            Console.WriteLine("   --"+Description);
        }

        public override void Add(MenuComponent menuComponent)
        {
            throw new NotImplementedException();
        }
    }

    public class Menu : MenuComponent
    {
        ArrayList menuComponents = new ArrayList();
        public string Name { get; set; }
        public string Description { get; set; }

        public Menu(string name, string description)
        {
            this.Name = name;
            this.Description = description;
        }

        public override void Add(MenuComponent menuComponent)
        {
            menuComponents.Add(menuComponent);
        }
        public override void Remove(MenuComponent menuComponent)
        {
            menuComponents.Remove(menuComponent);
        }
        public override MenuComponent  GetChild(int i)
        {
            return (MenuComponent)menuComponents[i];
        }

        public override void Print()
        {
            Console.Write("\n"+Name);
            Console.WriteLine(", "+Description);
            Console.WriteLine("--------------------");
            //Используем итератор для перебора всех компонентов объекта Меню
            IEnumerator iterator = menuComponents.GetEnumerator();
            while (iterator.MoveNext())
            {
                MenuComponent menuComponent = (MenuComponent)iterator.Current;
                menuComponent.Print();
            }
        }
    }

    public class DinnerMenu : Menu
    {
        public DinnerMenu(string name, string description) : base(name, description)
        {

            base.Add(new MenuItem("Манная каша", "Манная каша на миндальном молоке с ванилью", true, 120));
            base.Add(new MenuItem("Чечевичный суп", "Чечевичный суп с томатами", true, 150));
            base.Add(new MenuItem("Суп рассольник", "Постный рассольник", true, 180));
            base.Add(new MenuItem("Фаршированные перцы", "Фаршированные перцы с грибами и кабачком", true, 230));
            base.Add(new MenuItem("Овощное рагу", "Овощное рагу с мясом", false, 350));
            base.Add(new MenuItem("Свинина", "Свинина под лимонной заправкой", false, 550));
        }
    }

    public class BreakfastMenu : Menu
    {
        public BreakfastMenu(string name, string description):base(name,description)
        {
            base.Add(new MenuItem("Блиный гурман", "Блинчики со взбитыми яцами и тостом", true, 130));
            base.Add(new MenuItem("Блиный гурман", "Блинчики со взбитыми яцами и тостом", true, 130));
            base.Add(new MenuItem("Обычны завтра из блинов", "Жареный блин с сосиской", true, 130));
            base.Add(new MenuItem("Блины с черникой", "Блины со свежей черникой", true, 230));
            base.Add(new MenuItem("Фруктовые блины", "Блины со свежей черникой и клубникой", true, 230));
        }
    }

    public class Automatic
    {

        MenuComponent allMenus;

        public Automatic(MenuComponent allMenus)
        {
            this.allMenus = allMenus;
        }
        public void PrintMenu()
        {
            allMenus.Print();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MenuComponent breakfastMenu = new BreakfastMenu("Меню завтрак", "Завтрак");
            MenuComponent dinnerMenu = new DinnerMenu("Меню обеда", "Обед");

            MenuComponent allMenus = new Menu("Все меню","Общее меню");
       
            allMenus.Add(breakfastMenu);
            allMenus.Add(dinnerMenu);


            dinnerMenu.Add(new MenuItem("Паста", "Спагетти с соусом маринада и ломтик хлеба на закваске", true, 140));

            dinnerMenu.Add(breakfastMenu); //В меню обеда так же может входить и меню завтрака

            dinnerMenu.Add(new MenuItem("Фрукты", "Композиция из яблок, винограда, яблок, киви.", true, 130));
            

            Automatic automatic = new Automatic(allMenus);
            automatic.PrintMenu();

            Console.ReadKey();
        }
    }
}

Все меню, Общее меню
--------------------

Меню завтрак, Завтрак
--------------------
 Блиный гурман(v), 130
   --Блинчики со взбитыми яцами и тостом
 Блиный гурман(v), 130
   --Блинчики со взбитыми яцами и тостом
 Обычны завтра из блинов(v), 130
   --Жареный блин с сосиской
 Блины с черникой(v), 230
   --Блины со свежей черникой
 Фруктовые блины(v), 230
   --Блины со свежей черникой и клубникой

Меню обеда, Обед
--------------------
 Манная каша(v), 120
   --Манная каша на миндальном молоке с ванилью
 Чечевичный суп(v), 150
   --Чечевичный суп с томатами
 Суп рассольник(v), 180
   --Постный рассольник
 Фаршированные перцы(v), 230
   --Фаршированные перцы с грибами и кабачком
 Овощное рагу, 350
   --Овощное рагу с мясом
 Свинина, 550
   --Свинина под лимонной заправкой
 Паста(v), 140
   --Спагетти с соусом маринада и ломтик хлеба на закваске

Меню завтрак, Завтрак
--------------------
 Блиный гурман(v), 130
   --Блинчики со взбитыми яцами и тостом
 Блиный гурман(v), 130
   --Блинчики со взбитыми яцами и тостом
 Обычны завтра из блинов(v), 130
   --Жареный блин с сосиской
 Блины с черникой(v), 230
   --Блины со свежей черникой
 Фруктовые блины(v), 230
   --Блины со свежей черникой и клубникой
 Фрукты(v), 130
   --Композиция из яблок, винограда, яблок, киви.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.