Sunday, May 03, 2020

The command pattern




Encapsulate a request as an object, thereby allowing for the parameterization of clients with different requests and the queuing or logging of requests. It also allows for the support of undoable operations.


Problem

I'm building a digital game called War Tank, where the tank is capable of performing certain activities such as moving, firing and loading. These activities may be in a sequence, repetitive or reversed. The real-world implementation of this will result in a lot of code and complexity. But wait there's a Command pattern for this. 

Analysis 

We need to be able to encapsulate activities such as moving, loading and firing as objects. This would make issuing commands easy, by creating collections of commands that can be executed in any order.  

Solution 

Let's encapsulate each activity in a class of its own, now we have a MoveActivity class, LoadActivity class and FireActivity class. We create a layer of abstraction by inheriting these classes form a common abstract class called Activity.  Now we build our Tank class that's capable of executing these activities with a method called Action. The Action method can execute any Activity. The last thing we need is a TankCommander class that can invoke activities on a Tank. The TankCommander class binds the Tank to the Activities. 



Illustration





Code


    public class Program

    {

        static void Main()
        {
            Tank tank = new Tank();
            List Seq1 = new List {
                new LoadActivity(tank),
                new FireActivity(tank),
                new MoveActivity(tank)
            };

            TankCommander  tankCommander = new TankCommander();
            foreach (var command in Seq1)
            {  
                tankCommander.SetCommand(command);
                tankCommander.ExecuteCommand();
            }
            Console.ReadKey();
        }
    }
     
    public abstract class Activity
    {
        protected Tank battleVehicle;        
        public Activity(Tank battleVehicle)
        {
            this.battleVehicle = battleVehicle;
        }
        public abstract void Execute();
    }

    public class MoveActivity : Activity
    {
        public MoveActivity(Tank battleVehicle) :
          base(battleVehicle){}

        public override void Execute()
        {
            battleVehicle.Action("Moving Tank");
        }
    }

    public class LoadActivity : Activity
    {
        public LoadActivity(Tank battleVehicle) :
          base(battleVehicle){}

        public override void Execute()
        {
            battleVehicle.Action("Reloading guns");
        }
    }

    public class FireActivity : Activity
    { 
        public FireActivity(Tank battleVehicle) :
          base(battleVehicle){}

        public override void Execute()
        {
            battleVehicle.Action("Firing guns");
        }
    }

    public class Tank
    {
        public void Action(string _action)
        {
            Console.WriteLine(_action);
        }
    }
    public class TankCommander
    {
        private Activity command;

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

        public void ExecuteCommand()
        {
            command.Execute();
        }
    }

No comments: