Command Design Pattern

Command design pattern revolves around a single object which encapsulate all the information to execute a method at later time. This command object contains a receiver object instance and a method pointer.

A client can use command object with different parameters. Command object uses client parameters and execute the method on the receiver object.

Command design pattern is useful when we have to loosely coupled our code from the client and the receiver. A client does not know about the method and receiver object on which method is executing. Client simply calls the command object method and command object internally calls the receiver object method.

 

Structure of Command Pattern

Command Pattern

Participants

ICommand: ICommand is an interface which have only one method Execute.

ConcreteCommand: ConcreteCommand implements the ICommand interface. In the implemented method Execute, command is calling the Receiver action method.

Client:Client contains a reference to the CommandHolder object. 

CommandHolder: CommandHolder have the receiver object and ConcreteCommandObject.

Receiver: Receiver have the actuall implementation of the method which client want to call.

Example

Command-Example

In the above diagram, client have Trader object. Trader object have StockMarket object and two commands BuyCommand and SellCommand. Client call either BuyCommand or SellCommand to connect with StockMarket.

Command pattern provides loosely coupled code. Trader does not provide any reference to StockMarket object to the Client.

Below is the implementation of above diagram in C#.


    class Program
    {
        static void Main(string[] args)
        {
            Trader trader = new Trader();
            trader.BuyCommand.Execute(45); //buy 45 shares
            trader.SellCommand.Execute(23); //sell 23 shares
        }
    }

    public interface ICommand<T>
    {
        void Execute(T parameter);
    }

    public class DelegateCommand<T> : ICommand<T>
    {
        private Action<T> actionToInvoke;

        public DelegateCommand(Action<T> actionToInvoke)
        {
            this.actionToInvoke = actionToInvoke;
        }

        public void Execute(T parameter)
        {
            actionToInvoke.Invoke(parameter);
        }
    }

    public class Trader
    {
        private ShareMarket shareMarket;

        private DelegateCommand<int> buyCommand;
        private DelegateCommand<int> sellCommand;

        public Trader()
        {
            this.shareMarket = new ShareMarket();
        }

        public DelegateCommand<int> BuyCommand
        {
            get
            {
                if (this.buyCommand == null)
                {
                    this.buyCommand = new DelegateCommand<int>(w => this.OnBuyCommand(w));
                }
                return buyCommand;
            }
        }

        public DelegateCommand<int> SellCommand
        {
            get
            {
                if (this.sellCommand == null)
                {
                    this.sellCommand = new DelegateCommand<int>(w => this.OnSellCommand(w));
                }
                return this.sellCommand;
            }
        }

        private void OnBuyCommand(int parameter)
        {
            shareMarket.ConnectShareMarket();
            shareMarket.BuyShares(parameter);
            shareMarket.DisconnectWithShareMarket();
        }

        private void OnSellCommand(int parameter)
        {
            shareMarket.ConnectShareMarket();
            shareMarket.SellShares(parameter);
            shareMarket.DisconnectWithShareMarket();
        }
    }

    public class ShareMarket
    {
        public void ConnectShareMarket()
        {
        }

        public void BuyShares(int sharesToBuy)
        {
            Console.WriteLine("Buy shares: " + sharesToBuy);
        }

        public void SellShares(int sharesToSell)
        {
            Console.WriteLine("Sell shares: " + sharesToSell);
        }

        public void DisconnectWithShareMarket()
        {
        }
    }

Difference between Chain of Responsibility and Command Pattern

Chain of responsibility forwards the request to a chain of objects but the Command pattern forwards the request only to a specific object.