CSC/ECE 517 Fall 2007/wiki1b 7 as: Difference between revisions
mNo edit summary |
No edit summary |
||
Line 3: | Line 3: | ||
'''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. | ||
===Why use Command Patterns | ===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. | 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. | ||
Line 17: | Line 17: | ||
===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. | 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. | ||
====Implementation in Java==== | ====Implementation in Java==== | ||
Line 26: | Line 26: | ||
<code><pre> | <code><pre> | ||
import java.util.ArrayList; | |||
interface CommandPattern { | interface CommandPattern { | ||
void doCommand(); | void doCommand(); | ||
void undoCommand(); | void undoCommand(); | ||
} | |||
class NewString implements CommandPattern { | |||
private ArrayList<String> states = new ArrayList(); | |||
private String s; | |||
public NewString (String args) { | |||
s = args; | |||
} | |||
public ArrayList<String> getStates() { | |||
return states; | |||
} | |||
public void setStates(ArrayList<String> states) { | |||
this.states = states; | |||
} | |||
public void concat(String args) { | |||
doCommand(); | |||
s = s.concat(args); | |||
} | |||
public void doCommand() { | |||
states.add(this.s); | |||
} | |||
public void undoCommand() { | |||
if(states.size() > 0) { | |||
s = states.get(states.size()-1); | |||
states.remove(states.size()-1); | |||
} | |||
else | |||
System.out.println("no command done to undo"); | |||
} | |||
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"); | |||
System.out.println(s.getS()); | |||
s.undoCommand(); | |||
System.out.println(s.getS()); | |||
s.undoCommand(); | |||
System.out.println(s.getS()); | |||
} | |||
} | } | ||
</pre></code> | </pre></code> | ||
'''Sample Output: ''' | |||
<code><pre> | |||
$ sample | |||
$ sample123 | |||
$ sample | |||
$ no command done to undo | |||
</pre></code> | |||
====Implementation in Ruby==== | ====Implementation in Ruby==== | ||
Line 38: | Line 102: | ||
'''Example Code''' | '''Example Code''' | ||
<code><pre> | |||
$ irb | |||
module CommandPattern | |||
def undoCommand() | |||
if(@states.length > 0) | |||
initialize(@states.pop()) | |||
else | |||
puts "no command done to undo" | |||
end | |||
end | |||
def doCommand(object) | |||
if(@states == nil) | |||
@states = [] | |||
end | |||
@states.push(object) | |||
puts "docommand #{object}" | |||
end | |||
end | |||
class NewString < String | |||
include CommandPattern | |||
attr_accessor :states | |||
def initialize(arg) | |||
super(arg) | |||
end | |||
def concat(arg) | |||
doCommand(to_s()) | |||
super(arg) | |||
end | |||
end | |||
</pre></code> | |||
'''Sample Output: ''' | |||
<code><pre> | |||
>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 | |||
</pre></code> |
Revision as of 00:32, 2 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.
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.
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.
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;
interface CommandPattern {
void doCommand();
void undoCommand();
}
class NewString implements CommandPattern {
private ArrayList<String> states = new ArrayList();
private String s;
public NewString (String args) {
s = args;
}
public ArrayList<String> getStates() {
return states;
}
public void setStates(ArrayList<String> states) {
this.states = states;
}
public void concat(String args) {
doCommand();
s = s.concat(args);
}
public void doCommand() {
states.add(this.s);
}
public void undoCommand() {
if(states.size() > 0) {
s = states.get(states.size()-1);
states.remove(states.size()-1);
}
else
System.out.println("no command done to undo");
}
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");
System.out.println(s.getS());
s.undoCommand();
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
module CommandPattern
def undoCommand()
if(@states.length > 0)
initialize(@states.pop())
else
puts "no command done to undo"
end
end
def doCommand(object)
if(@states == nil)
@states = []
end
@states.push(object)
puts "docommand #{object}"
end
end
class NewString < String
include CommandPattern
attr_accessor :states
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