CSC/ECE 517 Fall 2010/ch4 4f ls: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 422: Line 422:
   
   
Transcript show: 'Argument #on or #off is required.'.
Transcript show: 'Argument #on or #off is required.'.
=Comparison: static vs dynamic=
Based on the above-mentioned examples, we present a short summary on comparison of command pattern in static language (such as Java) and dynamic language (such as ruby).
*


= Summary =
= Summary =

Revision as of 16:25, 31 October 2010

Topic: The Command pattern in static and dynamic languages

Fundamentals

What is Command Pattern ?

In object-oriented programming, the command pattern is a design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time[1]. This information includes the method name, the object that owns the method and values for the method parameters. Client, invoker and receiver are always associated with the command pattern. The client instantiates the command object and provides the information required to call the method at a later time. The invoker decides when the method should be called. The receiver is an instance of the class that contains the method's code. Using command objects makes it easier to construct general components that need to delegate, sequence or execute method calls at a time of their choosing without the need to know the owner of the method or the method parameters.

What are static and dynamic languages?

Dynamic programming language is used to describe a class of high-level programming languages that execute at runtime many common behaviors that other languages, which are usually called static language for convenience, might perform during compilation. These behaviors could include extension of the program, by adding new code, by extending objects and definitions, or by modifying the type system, all during program execution. These behaviors can be emulated in nearly any language of sufficient complexity, but dynamic languages provide direct tools to make use of them. Most dynamic languages are dynamically typed, but not all.

Actually, the notion of dynamic language is ambiguous sometime because it attempts to make distinctions between code and data as well as between compilation and runtime which are not universal. Virtual machines, just-in-time compilation, and the ability of many programming languages on some systems to directly modify machine code make the distinction abstract. In general, the assertion that a language is dynamic is more an assertion about the ease of use of dynamic features than it is a clear statement of the capabilities of the language. Particularly, the following are generally considered dynamic languages:

  • Ruby
  • Javascript
  • Perl
  • PHP
  • Smalltalk

Uses of Command Pattern

Command pattern encapsulates a request as an object, thereby letting you parametrize clients with different requests, queue or log requests, and support undoable operations. It is useful for implementing.

Structure

Terminology

We first introduce some terminology terms used to describe command pattern implementations.

  • Client: the button, toolbar button, or menu item clicked, the shortcut key pressed by the user.
  • Command: declares an interface for executing an operation;
  • Execute: It may refer to running the code identified by the command object's execute method.
  • Receiver: The actual work to be done by the command.
  • ConcreteCommand: extends the Command interface, implementing the Execute method by invoking the corresponding operations on Receiver. It defines a link between the Receiver and the action.
  • Invoker: It decides when the method should be called. It takes in the request and calls the receiver by passing the command to it and asks it to carry out the request.
  • Concretecommand:

Illustration

We will use the following graph to illustrate the structure of Command Pattern.

Why Command Pattern?

“An object that contains a symbol, name or key that represents a list of commands, actions or keystrokes”. This is the definition of a macro, one that should be familiar to any computer user. From this idea the Command design pattern was given birth. The Macro represents, at some extent, a command that is built from the reunion of a set of other commands, in a given order. Just as a macro, the Command design pattern encapsulates commands (method calls) in objects allowing us to issue requests without knowing the requested operation or the requesting object. Command design pattern provides the options to queue commands, undo/redo actions and other manipulations.

Advantages and Disadvantages of Using Command Pattern

Now that we have understood how the pattern works, it's time to take a look at its advantages and disadvantages.

The intelligence of a command

  • The command is just a link between the receiver and the actions that carry out the request.
  • The command implements everything itself, without sending anything to the receiver.

We must always keep in mind the fact that the receiver is the one who knows how to perform the operations needed, the purpose of the command being to help the client to delegate its request quickly and to make sure the command ends up where it should.

Advantages of Command Pattern

The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that know how to perform it.

  • It provides encapsulation of application logic so that it can be executed at a different point of time.
  • It allows to execute the application in separate contexts, such as in a different thread or using a different state by separating the application logic and context.
  • The separation between application logic and context allows to easier exchange the application logic.

Disadvantages of Command Pattern

The main benefits of the Command Pattern are discussed above. The major disadvantage of the pattern is that it results in lots of little Command classes that can clutter up a design. However, the routing information that Command objects encapsulate has to go somewhere. If this information is not contained in Command objects, then it will have to go into the Controller. The resulting bloat may necessitate partitioning the Controller into a subsystem, and it will certainly make the Controller harder to understand and maintain.

Command pattern in static and dynamic languages

In this section, we demonstrate the implementation of command pattern in both dynamic and static languages by some examples.

Command pattern in static languages

We consider in this article some typical static languages C#, java and C++.

C#

This structural code demonstrates the Command pattern which stores requests as objects allowing clients to execute or playback the requests.


// Command pattern -- Structural example
 using System;
 namespace DoFactory.GangOfFour.Command.Structural
{
 /// <summary>
 /// MainApp startup class for Structural
 /// Command Design Pattern.
 /// </summary>
 class MainApp
 {
   /// <summary>
   /// Entry point into console application.
   /// </summary>
   static void Main()
   {
     // 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();
   }
 } 
 /// <summary>
 /// The 'Command' abstract class
 /// </summary>
 abstract class Command
 {
   protected Receiver receiver;
   // Constructor
   public Command(Receiver receiver)
   {
     this.receiver = receiver;
   }
   public abstract void Execute();
 }
 /// <summary>
 /// The 'ConcreteCommand' class
 /// </summary>
 class ConcreteCommand : Command
 {
   // Constructor
   public ConcreteCommand(Receiver receiver) :
     base(receiver)
   {
   }
   public override void Execute()
   {
    receiver.Action();
   }
 }
 /// <summary>
 /// The 'Receiver' class
 /// </summary>
 class Receiver
 {
   public void Action()
   {
     Console.WriteLine("Called Receiver.Action()");
   }
 } 
/// <summary>
 /// The 'Invoker' class
 /// </summary>
 class Invoker
 {
   private Command _command
   public void SetCommand(Command command)
   {
     this._command = command;
   }
    public void ExecuteCommand()
   {
     _command.Execute();
   }
 }
}

Java

Sometimes it is necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request.” The Command design pattern suggests encapsulating (“wrapping”) in an object all (or some) of the following: an object, a method name, and some arguments. Java does not support “pointers to methods”, but its reflection capability will do nicely. The “command” is a black box to the “client”. All the client does is call “execute()” on the opaque object.

  import java.lang.reflect.*;
 public class CommandReflect {
  private int state;
  public CommandReflect( int in ) {
     state = in;
  }
  public int addOne( Integer one ) {
     return state + one.intValue();
  }
  public int addTwo( Integer one, Integer two ) {
     return state + one.intValue() + two.intValue();
  }
  static public class Command {
     private Object   receiver;               // the "encapsulated" object
     private Method   action;                 // the "pre-registered" request
     private Object[] args;                   // the "pre-registered" arg list
     public Command( Object obj, String methodName, Object[] arguments ) {
        receiver = obj;
        args = arguments;
        Class cls = obj.getClass();           // get the object's "Class"
        Class[] argTypes = new Class[args.length];
        for (int i=0; i < args.length; i++)   // get the "Class" for each
           argTypes[i] = args[i].getClass();  //    supplied argument
        // get the "Method" data structure with the correct name and signature
        try {      action = cls.getMethod( methodName, argTypes );      }
        catch( NoSuchMethodException e ) { System.out.println( e ); }
     }
     public Object execute() {
        // in C++, you do something like --- return receiver->action( args ); 
        try {     return action.invoke( receiver, args );     }
        catch( IllegalAccessException e    ) { System.out.println( e ); }
        catch( InvocationTargetException e ) { System.out.println( e ); }
        return null;
  }  }
  public static void main( String[] args ) {
     CommandReflect[] objs = { new CommandReflect(1), new CommandReflect(2) };
     System.out.print( "Normal call results: " );
     System.out.print( objs[0].addOne( new Integer(3) ) + " " );
     System.out.print( objs[1].addTwo( new Integer(4),
                                       new Integer(5) ) + " " );
     Command[] cmds = {
        new Command( objs[0], "addOne", new Integer[] { new Integer(3) } ),
        new Command( objs[1], "addTwo", new Integer[] { new Integer(4),
                                                        new Integer(5) } ) };
     System.out.print( "\nReflection results:  " );
     for (int i=0; i < cmds.length; i++)
         System.out.print( cmds[i].execute() + " " );
     System.out.println();
}  }

C++

   #include <iostream>  #include <string>  using namespace std;
   class Person;
   class Command
 {
   // 1. Create a class that encapsulates an object and a member function
   // a pointer to a member function (the attribute's name is "method")
   Person *object; //    
   void(Person:: *method)();
 public:
   Command(Person *obj = 0, void(Person:: *meth)() = 0)
   {
       object = obj; // the argument's name is "meth"
       method = meth;
   }
   void execute()
   {
       (object-> *method)(); // invoke the method on the object
   }

};

class Person {

   string name;
   // cmd is a "black box", it is a method invocation
   // promoted to "full object status"
   Command cmd; 
 public:
   Person(string n, Command c): cmd(c)
   {
       name = n;
   }
   void talk()
   {
       // "this" is the sender, cmd has the receiver
       cout << name << " is talking" << endl;
       cmd.execute(); // ask the "black box" to callback the receiver
   }
   void passOn()
   {
       cout << name << " is passing on" << endl;
       
       // 4. When the sender is ready to callback to the receiver,
       // it calls execute()
       cmd.execute(); 
   }
   void gossip()
   {
       cout << name << " is gossiping" << endl;
       cmd.execute();
   }
   void listen()
   {
       cout << name << " is listening" << endl;
   }
 };
 int main()
 {
 // Fred will "execute" Barney which will result in a call to passOn()
 // Barney will "execute" Betty which will result in a call to gossip()
 // Betty will "execute" Wilma which will result in a call to listen()
 Person wilma("Wilma", Command());
 // 2. Instantiate an object for each "callback"
 // 3. Pass each object to its future "sender"
 Person betty("Betty", Command(&wilma, &Person::listen));
 Person barney("Barney", Command(&betty, &Person::gossip));
 Person fred("Fred", Command(&barney, &Person::passOn));
 fred.talk();
 }

Command pattern in dynamic languages

In terms of dynamic languages, we consider PHP and Smalltalk.

PHP

In this example, a BookStarsOnCommand object is instantiated with an instance of the BookComandee class. The BookStarsOnCommand object will call that BookComandee object’s bookStarsOn() function when it’s execute() function is called.

  <?php
class BookCommandee {
   private $author;
   private $title;
   function __construct($title_in, $author_in) {
       $this->setAuthor($author_in);
       $this->setTitle($title_in);
   }
   function getAuthor() {
       return $this->author;
   }
   function setAuthor($author_in) {
       $this->author = $author_in;
   }
   function getTitle() {
       return $this->title;
   }
   function setTitle($title_in) {
       $this->title = $title_in;
   }
   function setStarsOn() {
       $this->setAuthor(Str_replace(' ','*',$this->getAuthor()));
       $this->setTitle(Str_replace(' ','*',$this->getTitle()));
   }
   function setStarsOff() {
       $this->setAuthor(Str_replace('*',' ',$this->getAuthor()));
       $this->setTitle(Str_replace('*',' ',$this->getTitle()));
   }
   function getAuthorAndTitle() {
       return $this->getTitle().' by '.$this->getAuthor();
   }
}
abstract class BookCommand {
   protected $bookCommandee;
   function __construct($bookCommandee_in) {
       $this->bookCommandee = $bookCommandee_in;
   }
   abstract function execute();
}
class BookStarsOnCommand extends BookCommand {
   function execute() {
       $this->bookCommandee->setStarsOn();
   }
}
class BookStarsOffCommand extends BookCommand {
   function execute() {
       $this->bookCommandee->setStarsOff();
   }

}

 writeln('BEGIN TESTING COMMAND PATTERN');
 writeln();

 $book = new BookCommandee('Design Patterns', 'Gamma, Helm, Johnson, and Vlissides');
 writeln('book after creation: ');
 writeln($book->getAuthorAndTitle());
 writeln();

 $starsOn = new BookStarsOnCommand($book);
 callCommand($starsOn);
 writeln('book after stars on: ');
 writeln($book->getAuthorAndTitle());
 writeln();

 $starsOff = new BookStarsOffCommand($book);
 callCommand($starsOff);
 writeln('book after stars off: ');
 writeln($book->getAuthorAndTitle());
 writeln();
 writeln('END TESTING COMMAND PATTERN');

 // the callCommand function demonstrates that a specified
 // function in BookCommandee can be executed with only 
 // an instance of BookCommand.
 function callCommand(BookCommand $bookCommand_in) {
   $bookCommand_in->execute();
 }
 function writeln($line_in) {
   echo $line_in."
"; }
?>

Smalltalk

In this example we configure the Switch with 2 commands: to turn the light on and to turn the light off.

 Object subclass: #Switch
 instanceVariableNames: 
   ' flipUpCommand flipDownCommand '
 classVariableNames: 
 poolDictionaries: 

 Object subclass: #Light
   instanceVariableNames: 
   classVariableNames: 
   poolDictionaries: 

 Object subclass: #PressSwitch
   instanceVariableNames: 
   classVariableNames: 
   poolDictionaries: 

 !Switch class methods !
 upMessage: flipUpMessage downMessge: flipDownMessage

^self new upMessage: flipUpMessage downMessge: flipDownMessage; yourself.! !

 !Switch methods !
 upMessage: flipUpMessage downMessge: flipDownMessage

flipUpCommand := flipUpMessage. flipDownCommand := flipDownMessage.!

 flipDown	

flipDownCommand perform.!

 flipUp

flipUpCommand perform.! !

 !Light methods !
 turnOff

Transcript show: 'The light is off'; cr.!

 turnOn

Transcript show: 'The light is on'; cr.! !

 !PressSwitch class methods !
 switch: state

" This is the test method "

| lamp switchUp switchDown switch | lamp := Light new. switchUp := Message receiver: lamp selector: #turnOn. switchDown := Message receiver: lamp selector: #turnOff.

switch := Switch upMessage: switchUp downMessge: switchDown.

state = #on ifTrue: [ ^switch flipUp ]. state = #off ifTrue: [ ^switch flipDown ].

Transcript show: 'Argument #on or #off is required.'.

Comparison: static vs dynamic

Based on the above-mentioned examples, we present a short summary on comparison of command pattern in static language (such as Java) and dynamic language (such as ruby).

Summary

In this article we took a quick look at the Command Pattern in static and dynamic languages. Command pattern is a great pattern for disconnecting the command originator and the system receiving the commands. This should be one of the first patterns you consider when thinking about creating a distributed type of system.

Furthermore, the comparison between command pattern in static languages and dynamic languages is actually the comparison between the static languages and dynamic languages. That is, in dynamic language, we can implement command pattern at runtime.

References

[1] Wikipedia - Command_Pattern. [Online]. http://en.wikipedia.org/wiki/Command_pattern

[2] Command Design Pattern. [Online]. http://sourcemaking.com/design_patterns/command

[3] Wikipedia - Dynamic programming language. [Online]. http://en.wikipedia.org/wiki/Dynamic_programming_language

[4] Wikipedia - Design Pattern. [Online]. http://en.wikipedia.org/wiki/Design_pattern_(computer_science)

[5] http://www.patterndepot.com/put/8/command.pdf

[6] Erich,G., Richard,H., Ralph,J.,and John,M.V. 1997. Design Patterns: Elements of Reusable Object-Oriented Software

[7] Freeman,E., Robson,E., Bates,B.,and Sierra,K. 2004. Head First Design Patterns