Skip to content
October 17, 2008 / Shrikant Patil

Behavioral Design Patterns : Command Design Pattern

Behavioral Design Patterns are specifically concerned with communication between the objects. The loose coupling is maintained between the communicating objects. In these patterns responsibilities are assigned between the objects through either inheritance or composition.  I have started looking into first pattern of the group, i.e Command Pattern.

The command pattern is a way where requests from the client for an object are assigned by encapsulating the details and receiver of the request. Consider a simple example, we use remote controller to change the channels while watching the television. Remote controller contains the buttons which are used to navigate from one channel to another. I used this remote and television concept to learn command pattern.

First I try to explain the base keywords of the pattern.

Client Object :
You are the one who is press the channel buttons on the remote control to switch between different channels. You know which channel you need to be switched and you press the button on remote accordingly. So client is responsible of creating the command object,
You –> Client Object

Command Object:
The Channel is the Command object in this model. All channel request implements a same interface and contains a execute () method which is get called by the Remote Controller (Invoker Object).
Channel -> Command Object

Invoker Object:
Remote Controller is the object which receives your command for channel change. It doesn’t know about which channel you are requesting instead it just call the method execute () on received Channel (Command ) Object. So Remote Controller (Invoker) object is totally unaware of what Command is going to do and who is going to receive the Command Object. It knows only that it will receive a Command Object, and that Command Object contains execute () method and need to call that method. So it invokes a method on Command Objects that’s why it is known as “Invoker” Object.
Remote Control –> Invoker

Receiver Object:
Television receives the request for channel change from the Command Object (Not from the Remote Controller, remote controller is totally unaware of the receiver, OK in real world remote controller sends the signal to change the channel to television). Every Command Objects contain a reference of the Receiver Object. In our case, each channelCommand Object contain a reference of Television. We know that remote controller only calls the execute() method on Channel (Command) object. In that method, channelChange() method is get called using the reference of Television by passing the current Channel name. Consider the concept here, Remote Controller is not calling any method of Television (it is totally unaware of both Command and Receiver). The Remote Controller calls execute() method of Channel (Command) Object and Channel (Command) object calls ChangeChannel() method on Television.
Television –> receiver

This is what the overview idea of the Pattern. At first it looks complex, but it is pretty easy concept. Let us have look at Definition and Diagram if the pattern.

Definition: The Command Pattern encapsulates a request as an object, thereby letting you parametrize other objects with different requests, queue or log requests and support undoable operations.

Let us try to understand the concept concentrating the above diagram;

ICommand Interface:
This is an Interface which declares the signature of method which needs to be implemented in ConcreteCommand objects. This Interface at least declare the signature of execute() method. The execute() method is get called by the Invoker Object.

ConcreteCommand:
This class implements ICommand Interface. This class holds a reference instance of receiver Object. The constructor needs a parameter to be passed of the type of Receiver Object. In execute() method of the class it calls action() method of the Receiver Object.

Receiver Object:
Receiver is last class of the mechanism; mean the execution of Command triggered at client ends at Receiver Object. It contains the methods which are get called by the ConcreteCommand Object’s execute() method.

Invoker Object:
The Invoker Object is responsible to call the execute() method on specific Command Object. The class defines a method setCommand() method which is used by the client Object to set the ConcreteCommand Object to Invoker Object. It stores each ConcreteCommand object in an array. It also provides another method which is get called by the client to stimulate an action on Invoker. Ex: In our case Remote Controller in Invoker, it contains two methods setChannel() which is used to set the ChannelCommand (ConcreteCommand Object). Each ChannelCommand is get stored in an array. The Remote Controller object also has another method onChannelChange() which receives an parameter of channel id. This method internally call the execute() method on specific ChannelCommand object by locating in array using passed channel id. It means when ever client press a remote controller button onChannelChange() method is get called on remote controller object to call execute() method of related ConcreteCommand.

Client Object:
Client object is responsible for creating the ConcreteCommands and setting them on Invoker Object. It also sets the Receiver for each ConcreteCommand. Client calls a method on Invoker object when client want to send a command to the Receiver. In our example, Client is  an interface which displays the remote controller buttons, on clicking the button the listener object calls onChannelChange() method on remote controller (Invoker)  object to stimulate the channel button press event.

Let us start coding our application.

Creating Command Interface :
The ICommand interface is defines the signature for ConcreteCommand object. It at least define the signature of execute() method.


package flexScript
{
    //interface for ConcreteCommand
    //it should atleast define the signaure of execute() method
    public interface ICommand
    {
        function execute():void;
    }
}

Creating ConcreteCommand Objects :
The concreteCommand object implements the interface of ICommand. In our application we only need one ConcreteComman object that is ChannelCommand. (Other Applications may need more than one ConcreteCommand Objects).


package flexScript
{
    //ConcreteCommand Object should implement Command Interface
    public class ChannelCommand implements ICommand
    {
        //Should hold the reference of Receiver Object(TV Object)
        private var tv:TV
        private var currentChannel:String;
        //Constructor needs to receive atleast a Receiver Object(TV Object)
        public function ChannelCommand(tel:TV, chnl:String)
        {
            //holds a reference Receiver Object(TV Object)
            this.tv = tel;
            this.currentChannel = chnl;
        }
        //implement the execute() signature
        public function execute():void
        {
            //call action() method on Receiver Object(TV Object)
            tv.changeChannel(currentChannel);
        }

    }
}


Creating Invoker Object:

In our case Invoker is Remote controller, which invokes execute() method of specific ConcreteCommand stored in array.


package flexScript
{
    public class RemoteControl
    {
        //uses an array to hold references of ConcreteCommands
        private var channels:Array;
        public function RemoteControl()
        {
            //initilize array
            channels = new Array();
        }

        //define setCommand() method to set ConcreteCommand Objects
        //on Invoker Object from client
        public function setChannel(ch:int, chName:ICommand):void{
            //store each referece of ConcreteCommand in array
            channels[ch] = chName;
        }

        //define method which is get called by client to stimulate
        //execute() method on specific ConcreteCommand
        public function onChannelChange(ch:int):void{
            //call execute() method on specific ConcreteCommand
            //stored in array
            channels[ch].execute();
        }

    }
}

Creating Receiver Object:
The Receiver object may be any of the object of the application. In out case TV object act as Receiver object. It contains a public method which is get called by specific ChannelCommand (ConacreteCommand) object to perform channel change operation.

package flexScript
{
    public class TV
    {
        private var currentChannel:String;
        //define a method which is get called by ConcreteCommand
        public function changeChannel(ch:String):void{
            //specify the channel change actions here
            trace("Tuening...");
            this.currentChannel = ch;
            trace("Tuned to New Channel :"+ch);
        }

    }
}

Creating Client Object :
Client class creates ChannelCommands (ConcreteCommands) and set them on Invoker Object passing TV (Receiver) object as parameter. Client also creates an UI which displays the remote buttons and assign a listener for click on the button. The listener will call onChannelChange() method of remote controller (Invoker).

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="init()">
<mx:Script>
    <!&#91;CDATA&#91;
    import flexScript.TV;
    import mx.events.ItemClickEvent;
    import flexScript.ChannelCommand;
    import flexScript.RemoteControl;

    //create Receiver Objet (TV Object)
    private var tele:TV = new TV();
    //create Invoker Object (RemoteControl)
    private var remote:RemoteControl = new RemoteControl();

    //create ConcreteCommand Objects (ChannelCommand)
    private var chn1:ChannelCommand = new ChannelCommand(tele,"ESPN");
    private var chn2:ChannelCommand = new ChannelCommand(tele,"BBC");
    private var chn3:ChannelCommand = new ChannelCommand(tele,"STAR");
    private var chn4:ChannelCommand = new ChannelCommand(tele,"HISTORY");
    private var chn5:ChannelCommand = new ChannelCommand(tele,"DISCOVERY");

    private function init():void{
        //set each ConcreteCommands(ChannelCommand)
        // to Invoker (RemoteControl)
        remote.setChannel(0,chn1);
        remote.setChannel(1,chn2);
        remote.setChannel(2,chn3);
        remote.setChannel(3,chn4);
        remote.setChannel(4,chn5);
    }

    //On button press listener
    private function chChange(e:MouseEvent):void{
        //call onChannelChange() method on Invoker (RemoteCOntrol)
        remote.onChannelChange(new int(e.target.label));
    }

    &#93;&#93;>
</mx:Script>
    <mx:LinkButton x="130" y="208" label="0" click="chChange(event)"/>
    <mx:LinkButton x="222" y="208" label="1" click="chChange(event)"/>
    <mx:LinkButton x="316" y="208" label="2" click="chChange(event)"/>
    <mx:LinkButton x="174" y="238" label="3" click="chChange(event)"/>
    <mx:LinkButton x="267" y="238" label="4" click="chChange(event)"/>
</mx:Application>

Run the code in flex Builder 3 debug mode. you will get the trace messages on output panel. (Please make sure that all class files should be in flexScript folder)
Hope, you enjoyed the pattern;

Advertisements

3 Comments

Leave a Comment
  1. Robert Berg / Aug 28 2009 7:53 pm

    Good example of the Command pattern as it relates to Flex. I will be refactoring my code to use this pattern.

    • ayumilove / Jan 24 2010 1:42 am

      Robert, you don’t force to fit your code into the design pattern, you let the design pattern comes naturally into your code.

  2. semodesign / Jun 26 2012 7:31 pm

    Thank you for the quite extensive Tutorial. It is really helpful for my exams to understand how to implement this GoF Pattern in Actionscript. =)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: