CSC/ECE 517 Fall 2007/wiki1b 7 as: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(15 intermediate revisions by the same user not shown)
Line 2: Line 2:


'''Definition''' : Command Pattern is a Design Pattern that encapsulates invocation and allows code that causes actions to be initiated to be separated from code that performs those actions.
'''Definition''' : Command Pattern is a Design Pattern that encapsulates invocation and allows code that causes actions to be initiated to be separated from code that performs those actions.
(the above definition was taken from wikipedia [http://en.wikipedia.org/wiki/Command_pattern])


===Why use Command Patterns?===
===Why use Command Patterns?===
Line 14: Line 16:
* Add new Commands, without having to change existing classes.
* Add new Commands, without having to change existing classes.


===Comparison between Command Pattern and similar Patterns===
There are other patterns that border in their working with Command Pattern, like Memento Pattern, and Chain-of-Responsibility pattern, Interpreter Pattern etc..
Commands and Mementos have some strong similarities due to the fact they both work with an object's internal properties. The Command pattern keeps a record of changes to an object's state, and applies those changes in an ad-hoc fashion. A Memento [http://en.wikipedia.org/wiki/Memento_pattern] also records changes to an object's state, and can restore that state at any time. The Chain of Responsibility [http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern] pattern seems to handle processing in a similar manner to the Command, except it hands off processing to another process linearly unlike the Command pattern. An Interpreter pattern [http://en.wikipedia.org/wiki/Interpreter_pattern] works in the example above because we are using language elements to determine which changes to apply at a given time.
Interceptor pattern [http://dailydevelopment.blogspot.com/2007/04/interceptor-design-pattern.html] implementation have many of the functionalities of Command patterns and Chain-of-Responsibility patterns due to its multiple uses in monitoring. Given a system, it helps in allowing others to monitor what goes on inside it and (optionally) change/extend some of its behavior without making ''others'' understand our code and without making them change our code and without affecting the system.


===Implementation of Command Patterns in Java Vs Ruby===
===Implementation of Command Patterns in Java Vs Ruby===


Both Java and Ruby are object oriented programming languages in which command pattern can be implemented by turning the request itself into an object. This object can be stored and passed around like other objects. The Receiver has the knowledge required to carry out the request. In Java the implementation is through ''interfaces'' and in Ruby the implementation is through ''mixins''. The difference in implementation of command patterns in Java and Ruby are brought out using a simple example that undos the concatination operation on strings. Because of concepts such as meta-programming, modules, mixins many of the design patterns have much simpler, cleaner implementations in Ruby.  
Both Java and Ruby are object oriented programming languages in which command pattern can be implemented by turning the request itself into an object. This object can be stored and passed around like other objects. The Receiver has the knowledge required to carry out the request. In Java the implementation is through ''interfaces'' and in Ruby the implementation is through ''mixins''. The difference in implementation of command patterns in Java and Ruby are brought out using a simple example that undos the concatenation operation on strings. Because of concepts such as meta-programming, modules, mixins many of the design patterns have much simpler, cleaner implementations in Ruby.  


In both Java and Ruby we have attempted to implement do-Undo concept as follows.  This concept is very useful in real life in just text editing but also for very complicated classes with appropriate definitions of do and undo.  We have have brought out the concept using string concatenation as an example.  Every time the object calls the concatenation function, we push the current state of the object into a stack and then allow it to be modified.  On the invocation of undo method, the stack is popped and the previous state is restored.
To illustrate the concept of command pattern we have attempted to implement ''do-undo concept'' in both Java and Ruby as follows.  This concept is very useful in real life, not just in text editing but also for very complicated classes in which the implementation needs to be decoupled from the invocation.  We have have brought out the concept of command patterns using string concatenation.  Every time the object calls the concatenation function, we push the current operation on the object into a stack and then allow it to be modified.  On the invocation of undo method, the stack is popped and operation is done in a reverse manner thus accomplishing the undo action.


====Implementation in Java====
====Implementation in Java====
Line 39: Line 48:


/*
/*
  * this NewString implements CommandPattern, and note: this cannot extend String class,
  * this NewString implements CommandPattern
* because String-class in java is 'final'
  */
  */
class NewString implements CommandPattern {
class NewString implements CommandPattern {
// Stores the result of the last operation.
private ArrayList<String> states = new ArrayList();
private ArrayList<String> lastRes = new ArrayList();
private String s;
// The string on which the concatenation operation is done
        private String s;
public NewString (String args) {
public NewString (String args) {
s = args;
s = args;
}
}
// returns the last operation result of the object
public ArrayList<String> getStates() {
public ArrayList<String> getResult() {
return states;
return lastRes;
}
}
 
        // current operation stored on to the ArrayList
public void setStates(ArrayList<String> states) {
public void setResult(ArrayList<String> opers) {
this.states = states;
this.lastRes = opers;
}
}
Line 65: Line 74:
         //this function is called when concat method is called. (the previous function)
         //this function is called when concat method is called. (the previous function)
         //we append current state to an ArrayList
         //we append current operation to an ArrayList
public void doCommand() {
public void doCommand() {
states.add(this.s);
lastRes.add(this.s);
}
}
         // this method does the undo operation.
         // this method does the undo operation.
         // the storage of states is done in an ArrayList, and hence we implemented our own
         // in this method redo the last operation in an ad-hoc fashion, to undo
         // way of 'popping' for the ArrayList
         // last operation
public void undoCommand() {
public void undoCommand() {
if(states.size() > 0) {
if(lastRes.size() > 0) {
s = states.get(states.size()-1);
s = lastRes.get(lastRes.size()-1);
states.remove(states.size()-1);
lastRes.remove(lastRes.size()-1);
}
}
else
else
System.out.println("no command done to undo");
System.out.println("no command done to undo");
}
}
 
        // the getter and setter methods for the string
public String getS() {
public String getS() {
return s;
return s;
}
}
public void setS(String s) {
public void setS(String s) {
this.s = s;
this.s = s;
Line 94: Line 102:
NewString s = new NewString("sample ");
NewString s = new NewString("sample ");
System.out.println(s.getS());
System.out.println(s.getS());
s.concat("123");
s.concat("123");//concatenating the string
System.out.println(s.getS());
System.out.println(s.getS());
s.undoCommand();
s.undoCommand();//removes the last modification of the NewString object
System.out.println(s.getS());
System.out.println(s.getS());
s.undoCommand();
s.undoCommand();
Line 121: Line 129:
$ irb
$ irb
# this is command pattern module which implements do undo operation  
# this is command pattern module which implements do undo operation  
# for any class/object.   
# for any class/object.  We store the last operation in a stack.
# note: there is no mention of type of object before pushing/popping in  
module CommandPattern
# 'states' (stack) variable
  //pops the previous operation from the stack
module CommandPattern
   def undoCommand()     
   def undoCommand()     
     if(@states.length > 0)
     if(@lastRes.length > 0)
         initialize(@states.pop())
         initialize(@lastRes.pop())
     else
     else
         puts "no command done to undo"
         puts "no command done to undo"
     end
     end
   end
   end
    
   //pushes the current operation of the stack
   def doCommand(object)
   def doCommand(object)
    
    
     if(@states == nil)
     if(@lastRes == nil)
       @states = []
       @lastRes = []
     end
     end
      
      
     @states.push(object)
     @lastRes.push(object)
     puts "docommand #{object}"  
     puts "docommand #{object}"  
   end
   end
end
end


# here we can extend any class to whatever functionality we want, while
# here we can extend any class to whatever functionality we want,
# java String class cannot be.
#by just including the module previously defined.
 
class NewString < String  
class NewString < String  
   include CommandPattern
   include CommandPattern
   attr_accessor :states
   attr_accessor :lastRes
   def initialize(arg)
   def initialize(arg)
     super(arg)
     super(arg)
Line 184: Line 190:
Ruby's dynamic typing does not mean weak typing—Ruby always requires you to pass objects of the correct type. Java, in fact, enforces types more weakly than Ruby. For example, Java evaluates "4" + 2 as "42", coercing the integer to a string, while Ruby throws a TypeError, telling you it "can't convert Fixnum into String." Likewise, Java, sacrificing correctness for speed, can silently overflow an integer operation, producing weirdness such as Integer.MAX_VALUE + 1, which equals Integer.MIN_VALUE, while Ruby simply expands integers as needed."
Ruby's dynamic typing does not mean weak typing—Ruby always requires you to pass objects of the correct type. Java, in fact, enforces types more weakly than Ruby. For example, Java evaluates "4" + 2 as "42", coercing the integer to a string, while Ruby throws a TypeError, telling you it "can't convert Fixnum into String." Likewise, Java, sacrificing correctness for speed, can silently overflow an integer operation, producing weirdness such as Integer.MAX_VALUE + 1, which equals Integer.MIN_VALUE, while Ruby simply expands integers as needed."


In our Ruby implementation, the command pattern for undo is coded as a module, what can be included for any class or just an object. While in Java, its been implemented as an interface forcing it be implemented by every class that needs this functionality.  Also, implementing it as a separate module makes 'do' and 'undo' code to be written only once and any object/class can be extended easily. While in Java, each class that implements this interface must have a separate definition for the code. This has several disadvantages like increases code complexity, size and is generally confusing and tedious to trace or understand the code.
These are the similarities and differences we noted down while browsing net trying to compare java and Ruby. [http://www.ruby-lang.org/en/documentation/]
 
====Similarities====
 
As with Java, in Ruby,...
 
    * Memory is managed for you via a garbage collector.
    * Objects are strongly typed.
    * There are public, private, and protected methods.
    * There are embedded doc tools (Ruby’s is called RDoc). The docs generated by rdoc look very similar to those
      generated by javadoc.
 
====Differences====
 
Unlike Java, in Ruby,...
 
    * You don’t need to compile your code. You just run it directly.
    * There are different GUI toolkits. Ruby users can try WxRuby, FXRuby, Ruby-GNOME2, or the bundled-in Ruby Tk
      for example.
    * You use the end keyword after defining things like classes, instead of having to put braces around blocks
      of code.
    * You have require instead of import.
    * All member variables are private. From the outside, you access everything via methods.
    * Parentheses in method calls are usually optional and often omitted.
    * Everything is an object, including numbers like 2 and 3.14159.
    * There’s no static type checking.
    * Variable names are just labels. They don’t have a type associated with them.
    * There are no type declarations. You just assign to new variable names as-needed and they just “spring up”
      (i.e. a = [1,2,3] rather than int[] a = {1,2,3};).
    * There’s no casting. Just call the methods. Your unit tests should tell you before you even run the code if
      you’re going to see an exception.
    * It’s foo = Foo.new( "hi") instead of Foo foo = new Foo( "hi" ).
    * The constructor is always named “initialize” instead of the name of the class.
    * You have “mixin’s” instead of interfaces.
    * YAML tends to be favored over XML.
    * It’s nil instead of null.
    * == and equals() are handled differently in Ruby. Use == when you want to test equivalence in Ruby (equals()
      is Java). Use equal?() when you want to know if two objects are the same (== in Java).
 
===Conclusion===
 
In our Ruby implementation, the command pattern for undo is coded as a module, which can be included for any class or an object. While in Java, its been implemented as an interface forcing it be implemented by every class that needs this functionality.  Also, implementing it as a separate module makes 'do' and 'undo' code to be written only once and any object/class can be extended easily. While in Java, each class that implements this interface must have a separate definition for the code. This has several disadvantages like increases code complexity, size and is generally confusing and tedious to trace or understand the code.


==References==
==References==
*Wikipedia page, [http://en.wikipedia.org/wiki/Command_pattern]
*Wikipedia page, [http://en.wikipedia.org/wiki/Command_pattern]
*Javaworld, a pretty detailed discussion on pros and cons of using java and ruby for various purposes. [http://www.javaworld.com/javaworld/jw-07-2006/jw-0717-ruby.html]
*Javaworld, a pretty detailed discussion on pros and cons of using java and ruby for various purposes. [http://www.javaworld.com/javaworld/jw-07-2006/jw-0717-ruby.html]
*Example of Undo Implementation [http://c2.com/cgi/wiki?CommandPattern]
==Further Reading==
*Design Patterns: A good starting point [http://en.wikipedia.org/wiki/Design_pattern_(computer_science)]
*How to implement Command Pattern in java [http://www.javaworld.com/javaworld/javatips/jw-javatip68.html]
*How to implement Command Pattern in java [http://www.javaworld.com/javaworld/javatips/jw-javatip68.html]
*Example of Undo Implementation [http://c2.com/cgi/wiki?CommandPattern]
*Advanced topics on Ruby[http://ruby.about.com/od/advancedruby/Advanced_Ruby.htm]
*A good explanation of Ruby functionalities [http://peter.michaux.ca/article/1174]
*An elementary tutorial on Design Pattern [http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/patterns/]
*For further reading [http://ruby.about.com/od/advancedruby/Advanced_Ruby.htm]
*A Good Books. Design patterns in java [http://www.amazon.com/Design-Patterns-Java-Workbook-Software/dp/0201743973]


==Contributors==
==External Links==
*Ashwin Veeravalli [http://ashwin.gopalakrishnan.googlepages.com/]
*http://www.vincehuston.org/dp/command.html
*Satya N Viswanathan [http://vsn314.googlepages.com/test1]
*http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/
*http://www.patterndepot.com/put/8/JavaPatterns.htm
*http://www.stardeveloper.com/articles/display.html?article=2004022804&page=1
*http://www.mactech.com/articles/mactech/Vol.13/13.04/DesignPatternsTutorial/index.html

Latest revision as of 01:19, 11 October 2007

Command Patterns

Definition : Command Pattern is a Design Pattern that encapsulates invocation and allows code that causes actions to be initiated to be separated from code that performs those actions.

(the above definition was taken from wikipedia [1])

Why use Command Patterns?

A Command pattern is an object behavioral pattern that allows us to achieve complete decoupling between the sender and the receiver. (A sender is an object that invokes an operation, and a receiver is an object that receives the request to execute a certain operation. With decoupling, the sender has no knowledge of the Receiver's request.) The term request here refers to the command that is to be executed. The Command pattern also allows us to vary when and how a request is fulfilled. Therefore, a Command pattern provides us flexibility as well as extensibility.


Use of Command Patterns

  • Decouple the object that invokes the operation from the one that performs the action described earlier.
  • Assemble commands into a composite command.
  • Add new Commands, without having to change existing classes.

Comparison between Command Pattern and similar Patterns

There are other patterns that border in their working with Command Pattern, like Memento Pattern, and Chain-of-Responsibility pattern, Interpreter Pattern etc..

Commands and Mementos have some strong similarities due to the fact they both work with an object's internal properties. The Command pattern keeps a record of changes to an object's state, and applies those changes in an ad-hoc fashion. A Memento [2] also records changes to an object's state, and can restore that state at any time. The Chain of Responsibility [3] pattern seems to handle processing in a similar manner to the Command, except it hands off processing to another process linearly unlike the Command pattern. An Interpreter pattern [4] works in the example above because we are using language elements to determine which changes to apply at a given time.

Interceptor pattern [5] implementation have many of the functionalities of Command patterns and Chain-of-Responsibility patterns due to its multiple uses in monitoring. Given a system, it helps in allowing others to monitor what goes on inside it and (optionally) change/extend some of its behavior without making others understand our code and without making them change our code and without affecting the system.

Implementation of Command Patterns in Java Vs Ruby

Both Java and Ruby are object oriented programming languages in which command pattern can be implemented by turning the request itself into an object. This object can be stored and passed around like other objects. The Receiver has the knowledge required to carry out the request. In Java the implementation is through interfaces and in Ruby the implementation is through mixins. The difference in implementation of command patterns in Java and Ruby are brought out using a simple example that undos the concatenation operation on strings. Because of concepts such as meta-programming, modules, mixins many of the design patterns have much simpler, cleaner implementations in Ruby.

To illustrate the concept of command pattern we have attempted to implement do-undo concept in both Java and Ruby as follows. This concept is very useful in real life, not just in text editing but also for very complicated classes in which the implementation needs to be decoupled from the invocation. We have have brought out the concept of command patterns using string concatenation. Every time the object calls the concatenation function, we push the current operation on the object into a stack and then allow it to be modified. On the invocation of undo method, the stack is popped and operation is done in a reverse manner thus accomplishing the undo action.

Implementation in Java

The key to implementing command patterns in Java are interfaces, which declare the executing operations. In its simplest form, this interface includes an abstract execute operation. Each concrete Command class specifies a receiver-action pair by storing the Receiver as an instance variable. It provides different implementations of the execute() method to invoke the request.

Example Code

import java.util.ArrayList;

/*
 * Basic interface for do-undo command pattern. 
 */
interface CommandPattern {
	void doCommand();
	void undoCommand();
}

/*
 * this NewString implements CommandPattern
 */
class NewString implements CommandPattern {
	// Stores the result of the last operation.
	private ArrayList<String> lastRes = new ArrayList();
	// The string on which the concatenation operation is done
        private String s;
	
	public NewString (String args) {
		s = args;
	}
	// returns the last operation result of the object
	public ArrayList<String> getResult() {
		return lastRes;
	}
        // current operation stored on to the ArrayList
	public void setResult(ArrayList<String> opers) {
		this.lastRes = opers;
	}
	
	public void concat(String args) {
		doCommand();
		s = s.concat(args);
	}
	
        //this function is called when concat method is called. (the previous function)
        //we append current operation to an ArrayList
	public void doCommand() {
		lastRes.add(this.s);
	}
	
        // this method does the undo operation.
        // in this method redo the last operation in an ad-hoc fashion, to undo
        // last operation
	public void undoCommand() {
		if(lastRes.size() > 0) {
			s = lastRes.get(lastRes.size()-1);
			lastRes.remove(lastRes.size()-1);
		}
		else
			System.out.println("no command done to undo");
	}
        // the getter and setter methods for the string
	public String getS() {
		return s;
	}
	public void setS(String s) {
		this.s = s;
	}
	
	public static void main(String[] args) {
	
		NewString s = new NewString("sample ");
		System.out.println(s.getS());
		s.concat("123");//concatenating the string
		System.out.println(s.getS());
		s.undoCommand();//removes the last modification of the NewString object
		System.out.println(s.getS());
		s.undoCommand();
		System.out.println(s.getS());
	}
}

Sample Output:

$ sample
$ sample123
$ sample
$ no command done to undo

Implementation in Ruby

The key to implementing command patterns in Java are mixins, which define the executing operations. In its simplest form, this mixin include the implementation of the execute operation. Each Command class that specifies a receiver-action pair by storing the Receiver as an instance includes the mixin and calls the execute operation of the mixin.

Example Code

$ irb
# this is command pattern module which implements do undo operation 
# for any class/object.  We store the last operation in a stack.
module CommandPattern
  //pops the previous operation from the stack
  def undoCommand()    
    if(@lastRes.length > 0)
        initialize(@lastRes.pop())
    else
        puts "no command done to undo"
    end
  end
  //pushes the current operation of the stack
  def doCommand(object)
  
    if(@lastRes == nil)
      @lastRes = []
    end
    
    @lastRes.push(object)
    puts "docommand #{object}" 
  end
end

# here we can extend any class to whatever functionality we want,
#by just including the module previously defined.
class NewString < String 
  include CommandPattern
  attr_accessor :lastRes
  def initialize(arg)
    super(arg)
  end
  def concat(arg)
    doCommand(to_s())
    super(arg)
    
  end
end

Sample Output:

>a = NewString.new("sample")
>puts a
>>sample
>a.concat("123")
>puts a
>>sample123
>a.undoCommand()
>puts a
>>sample
>a.undoCommand()
>>no command done to undo

Advantages of Ruby over Java

The following explanation from the webpage [6] captures the advantages of Ruby implementation of command patterns over Java in a succinct and clear manner.

"Execute() methods in the Command design pattern must return Object rather than a specific type in pre-Java 5 code, resulting in ClassCastExceptions. Likewise, when signatures change between compile-time and runtime, runtime Errors ensue. In practice, whether in Java or Ruby, such errors rarely cause severe field bugs. A strong unit test suite—which you need anyway!—generally catches them in time.

Ruby's dynamic typing does not mean weak typing—Ruby always requires you to pass objects of the correct type. Java, in fact, enforces types more weakly than Ruby. For example, Java evaluates "4" + 2 as "42", coercing the integer to a string, while Ruby throws a TypeError, telling you it "can't convert Fixnum into String." Likewise, Java, sacrificing correctness for speed, can silently overflow an integer operation, producing weirdness such as Integer.MAX_VALUE + 1, which equals Integer.MIN_VALUE, while Ruby simply expands integers as needed."

These are the similarities and differences we noted down while browsing net trying to compare java and Ruby. [7]

Similarities

As with Java, in Ruby,...

   * Memory is managed for you via a garbage collector.
   * Objects are strongly typed.
   * There are public, private, and protected methods.
   * There are embedded doc tools (Ruby’s is called RDoc). The docs generated by rdoc look very similar to those
     generated by javadoc.

Differences

Unlike Java, in Ruby,...

   * You don’t need to compile your code. You just run it directly.
   * There are different GUI toolkits. Ruby users can try WxRuby, FXRuby, Ruby-GNOME2, or the bundled-in Ruby Tk
     for example.
   * You use the end keyword after defining things like classes, instead of having to put braces around blocks 
     of code.
   * You have require instead of import.
   * All member variables are private. From the outside, you access everything via methods.
   * Parentheses in method calls are usually optional and often omitted.
   * Everything is an object, including numbers like 2 and 3.14159.
   * There’s no static type checking.
   * Variable names are just labels. They don’t have a type associated with them.
   * There are no type declarations. You just assign to new variable names as-needed and they just “spring up” 
     (i.e. a = [1,2,3] rather than int[] a = {1,2,3};).
   * There’s no casting. Just call the methods. Your unit tests should tell you before you even run the code if 
     you’re going to see an exception.
   * It’s foo = Foo.new( "hi") instead of Foo foo = new Foo( "hi" ).
   * The constructor is always named “initialize” instead of the name of the class.
   * You have “mixin’s” instead of interfaces.
   * YAML tends to be favored over XML.
   * It’s nil instead of null.
   * == and equals() are handled differently in Ruby. Use == when you want to test equivalence in Ruby (equals() 
     is Java). Use equal?() when you want to know if two objects are the same (== in Java).

Conclusion

In our Ruby implementation, the command pattern for undo is coded as a module, which can be included for any class or an object. While in Java, its been implemented as an interface forcing it be implemented by every class that needs this functionality. Also, implementing it as a separate module makes 'do' and 'undo' code to be written only once and any object/class can be extended easily. While in Java, each class that implements this interface must have a separate definition for the code. This has several disadvantages like increases code complexity, size and is generally confusing and tedious to trace or understand the code.

References

  • Wikipedia page, [8]
  • Javaworld, a pretty detailed discussion on pros and cons of using java and ruby for various purposes. [9]
  • Example of Undo Implementation [10]

Further Reading

  • Design Patterns: A good starting point [11]
  • How to implement Command Pattern in java [12]
  • Advanced topics on Ruby[13]
  • An elementary tutorial on Design Pattern [14]

External Links