Паттерн Команда примеры на C#

Паттерн Команда инкапсулирует запрос в виде объекта, делая возможной параметризацию клиентских объектов с другими запросами, организацию очереди или регистрацию запросов, а также поддержку отмены операций.


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


Инициатор вызываем метод Execute() объекта команды что приводит к выполнению соответствующих операций с получателем. Паттерн команды могут поддерживать механизмы отмены, восстанавливающий объект в состоянии до последнего вызова метода Execute();


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


Команды также могут использоваться для реализации система регистрации команд и поддержки транзакций.

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

Пример 1 представим мы разрабатываем систему умный дом, у нас есть ТЗ которая подразумевает управление освещением в доме. Я не стал усложнять пример, отдельно взятой комнате, будем включать и выключать освещение во всем доме)

using System;

namespace Паттерн_Команда
{
    /// <summary>
    /// Единственный интерфейс с 2 методами
    /// </summary>
    public interface Command
    {
        void Execute();
        void Undo();
    }

    public class LightCommand : Command
    {
        Light light;
        public LightCommand(Light light) => this.light = light;

        public void Execute() => light.On();

        public void Undo() => light.Off();
    }

    /// <summary>
    /// Класс управляет набором объектов команд, при нажамии одной из кнопок активизируем методы Execute Undo
    /// Сам класс ничего не знает о тех классах, к которым он обращается, так как он отделен от них объектом команды
    /// </summary>
    public class SimpleRemoteControl
    {
        Command slot;
        public SimpleRemoteControl() { }

        public void SetCommand(Command command) => slot = command;
        public void ButtonOn() => slot.Execute();
        public void ButtonOff() => slot.Undo();
    }

    public class Light
    {
        public Light(){}
        public void Off() => Console.WriteLine("Выключили свет");
        public void On() => Console.WriteLine("Включили свет");
    }
    class Program
    {
        static void Main(string[] args)
        {
            SimpleRemoteControl remote = new SimpleRemoteControl();
            LightCommand lightCommand = new LightCommand(new Light());

            remote.SetCommand(lightCommand);
            remote.ButtonOn();

            remote.ButtonOff();
            Console.ReadKey();
        }
    }
}

 

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

using System;
using System.Collections.Generic;

namespace Паттерн_Команда
{
    ///// <summary>
    ///// Единственный интерфейс с 2 методами
    ///// </summary>
    public interface Command
    {
        void Execute();
        void Undo();
    }
    public enum Mode
    {
        High = 3,
        Medium = 2,
        Low = 1,
        Off = 0,
    }
    public class CeilingFan
    {
     
        Mode speed;
        string location;

        public CeilingFan(string location)
        {
            this.location = location;
            speed = Mode.Off;
        }

        public void High()
        {
            speed = Mode.High;
        }

        public void Medium()
        {
            speed = Mode.Medium;
        }

        public void Low()
        {
            speed = Mode.Low;
        }

        public void Off()
        {
            speed = Mode.Off;
        }

        public Mode GetSpeed()
        {
            return speed;
        }


    }


    internal class CeilingFanOffCommand : Command
    {
        private CeilingFan ceilingFan;
        Mode prevSpeed;
        public CeilingFanOffCommand(CeilingFan ceilingFan)
        {
            this.ceilingFan = ceilingFan;
        }

        public void Execute()
        {
            prevSpeed = ceilingFan.GetSpeed();
            ceilingFan.Off();
            Console.WriteLine("Режим выключения");
        }

        public void Undo()
        {
            switch (prevSpeed)
            {
                case Mode.High:
                    ceilingFan.High();
                    break;
                case Mode.Medium:
                    ceilingFan.Medium();
                    break;
                case Mode.Low:
                    ceilingFan.Low();
                    break;
                case Mode.Off:
                    ceilingFan.Off();
                    break;
            }
            Console.WriteLine("Возобновили режим выключения");
        }
    }

    internal class CeilingFanMediumCommand : Command
    {
        private CeilingFan ceilingFan;
        Mode prevSpeed;
        public CeilingFanMediumCommand(CeilingFan ceilingFan)
        {
            this.ceilingFan = ceilingFan;
        }

        public void Execute()
        {
            prevSpeed = ceilingFan.GetSpeed();
            ceilingFan.Medium();
            Console.WriteLine("Режим средней мощности");
        }

        public void Undo()
        {
            switch (prevSpeed)
            {
                case Mode.High:
                    ceilingFan.High();
                    break;
                case Mode.Medium:
                    ceilingFan.Medium();
                    break;
                case Mode.Low:
                    ceilingFan.Low();
                    break;
                case Mode.Off:
                    ceilingFan.Off();
                    break;
            }

            Console.WriteLine("Возобновили режим средней мощности");
        }
    }

    public class CeilingFanHighCommand : Command
    {
        CeilingFan ceilingFan;
        Mode prevSpeed;
        public CeilingFanHighCommand(CeilingFan ceilingFan)
        {
            this.ceilingFan = ceilingFan;
        }

        public void Execute()
        {
            prevSpeed = ceilingFan.GetSpeed();
            ceilingFan.High();
        }

        public void Undo()
        {
            switch (prevSpeed)
            {
                case Mode.High:
                    ceilingFan.High();
                    break;
                case Mode.Medium:
                    ceilingFan.Medium();
                    break;
                case Mode.Low:
                    ceilingFan.Low();
                    break;
                case Mode.Off:
                    ceilingFan.Off();
                    break;
            }
            Console.WriteLine("Режим максимальной мощности");
        }
    }
    ///// <summary>
    ///// Класс управляет набором объектов команд, при нажамии одной из кнопок активизируем методы Execute UnExecute
    ///// Сам класс ничего не знает о тех классах, к которым он обращается, так как он отделен от них объектом команды
    ///// </summary>
    public class SimpleRemoteControl
    {
        List<Command> onCommands;
        List<Command> offCommands;
        Command undoCommand;
        public SimpleRemoteControl() 
        {
            onCommands = new List<Command>{null,null,null,null,null,null};
            offCommands = new List<Command> { null, null, null, null, null, null };

        }

        public void SetCommand(int slot, Command command, Command offComand)
        {
            onCommands[slot] = command;
            offCommands[slot] = offComand;
        }

        public void ButtonOn(int slot)
        {
            onCommands[slot].Execute();
            undoCommand = onCommands[slot];
            Console.WriteLine("Включили вентелятор");
        }

        public void ButtonOff(int slot)
        {
            offCommands[slot].Execute();
            undoCommand = offCommands[slot];
            Console.WriteLine("Выключили вентелятор");
        }

        internal void ButtonUndo()
        {
            undoCommand.Undo();
            Console.WriteLine("Возврат предыдущего режима");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            SimpleRemoteControl remoteControl = new SimpleRemoteControl();
            CeilingFan ceilingFan = new CeilingFan("Спальня");

            CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
            CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan); //создаем экземпляры 3 команды высокой, средней и для выключения
            CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
            
            
            remoteControl.SetCommand(0, ceilingFanMedium, ceilingFanOff);
            remoteControl.SetCommand(1, ceilingFanHigh, ceilingFanOff);

            remoteControl.ButtonOn(0);
            remoteControl.ButtonOff(0);
            remoteControl.ButtonUndo();

            remoteControl.ButtonOn(1);
            remoteControl.ButtonUndo();



            Console.ReadKey();
        }
    }
}

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

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

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