STUDY/Design Pattern

명령패턴 (Command Pattern)

디리릭 2022. 12. 28. 21:56
728x90

요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 원하는 시점에 이용할 수 있도록, 매서드 이름, 매개변수 등의 요청에 사용되는 정보를 로깅, 취소 할 수 있는 패턴이다.

이 패턴을 통해 책임을 분산할 수 있다.

구조

▷ Command : 요청을 실행하기 위한 인터페이스

▷ ConcreteCommand : Receiver object 와 action간의 바인딩을 정의한다. Receiver에서 대응하는 동작을 Invoking에서 실행시키는 것을 구현

▷ Receiver : 받은 요청 수행에 대한 세부 동작

▷ Invoker : Command에 task 요청

구현

기본 >>

 abstract class Command

    {
        protected Receiver receiver;

        // Constructor

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }

        public abstract void Execute();
    }
    
    ===========================================
    
    class ConcreteCommand : Command

    {
        // Constructor

        public ConcreteCommand(Receiver receiver) :
          base(receiver)
        {
        }

        public override void Execute()
        {
            receiver.Action();
        }
    }
    
    ===========================================
    
     class Receiver

    {
        public void Action()
        {
            Console.WriteLine("Called Receiver.Action()");
        }
    }
    
     ===========================================
     
      class Invoker

    {
        private Command _command;

        public void SetCommand(Command command)
        {
            this._command = command;
        }

        public void ExecuteCommand()
        {
            _command.Execute();
        }
    }
    
     ===========================================
     
       static void Main(string[] args)
        {
            // Create receiver, command, and invoker

            Receiver receiver = new Receiver();
            Command command = new ConcreteCommand(receiver);
            Invoker invoker = new Invoker();

            // Set and execute command

            invoker.SetCommand(command);
            invoker.ExecuteCommand();

            // Wait for user

            Console.ReadKey();
        }

RESULT >>

응용 >>>

여기서는 Reciver을 따로 구현하지 않고 ConcreteCommand의 Execute 함수 내에서 구현이 되어 있다.

   public class Picture
    {
        public string Name 
        {
            get;
            private set;
        }
        public string User 
        {
            get;
            private set;
        }
        public Picture(string name, string user)
        {
            Name = name;
            User = user;
        }
    }
    
    =================================================
    
      public interface IExecute
    {
        void Execute(Picture picture);
    }
    
    =================================================
    
        public class ViewPicture : IExecute
    {
        public void Execute(Picture picture)
        {
            Console.WriteLine("사진 파일명:{0}", picture.Name);
        }
    }

    class ViewVerifyPicture : IExecute
    {
        public void Execute(Picture picture)
        {
            Console.WriteLine("[사진 파일명] {0} [소유자] {1}", picture.Name, picture.User);
        }
    }
    
    =================================================
    
    class PictureManager
    {
        List<Picture> pictures = new List<Picture>();

        public void AddPicture(string name, string user) 
        {
            pictures.Add(new Picture(name, user));
        }
        public void DoItAllPicture(IExecute command) 
        {
            foreach (var item in pictures)
            {
                command.Execute(item);
            }
        }
    }
    
    =================================================
    
       enum CommandEnum
    {
        VIEW,
        VIEW_VERIFY
    }

    class UIPart
    {
        PictureManager pm = new PictureManager();
        IExecute[] commands = new IExecute[2];
        string user = string.Empty;

        public UIPart() 
        {
            commands[0] = new ViewPicture();
            commands[1] = new ViewVerifyPicture();
        }
        public void Login(string user) 
        {
            this.user = user;
        }
        public void SavePicture(string name) 
        {
            if (user == string.Empty)
            {
                Console.WriteLine("먼저 로그 인을 하십시오.");
            }
            else 
            {
                pm.AddPicture(name, user);
            }
        }
        public void DoItCommand(CommandEnum cmd) 
        {
            pm.DoItAllPicture(commands[(int)cmd]);
        }
    }
    
    
    =================================================
    
      static void Main(string[] args)
        {
            UIPart up = new UIPart();
            up.Login("홍길동");
            up.SavePicture("독사진");
            up.Login("느린공장");
            up.SavePicture("공장사진");
            up.DoItCommand(CommandEnum.VIEW);
            up.DoItCommand(CommandEnum.VIEW_VERIFY);
            Console.Read();
        }

RESULT >>>>

WPF의 ICommand와 유사한 패턴임을 알 수 있다.

728x90