CSC/ECE 517 Fall 2007/wiki1b 7 c9: Difference between revisions
No edit summary |
|||
Line 218: | Line 218: | ||
=References= | =References= | ||
[http://www.rubygarden.org/Ruby/page/show/CommandPattern Ruby: Command Pattern] | *[http://www.rubygarden.org/Ruby/page/show/CommandPattern Ruby: Command Pattern] | ||
*[Lecture notes provided by Dr. Gehringer on Command Pattern http://courses.ncsu.edu/csc517/common/lectures/notes/lec10.pdf] | |||
*[http://en.wikipedia.org/wiki/Command_pattern Wikipedia Command Pattern] | |||
*[http://www.javaworld.com/javaworld/javatips/jw-javatip68.html?page=1 Learn How to Implement Command Pattern in Java] | |||
[http://en.wikipedia.org/wiki/Command_pattern Wikipedia Command Pattern] | *[http://www.javaworld.com/javaworld/jw-07-2006/jw-0717-ruby.html Ruby for the Java World] | ||
[http://www.javaworld.com/javaworld/javatips/jw-javatip68.html?page=1 Learn How to Implement Command Pattern in Java] | *Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Design Patterns Elements of Reusable Object-Oriented Software Addison-Wesley, 1995 | ||
[http://www.javaworld.com/javaworld/jw-07-2006/jw-0717-ruby.html Ruby for the Java World] | *Eric Freeman, and Elisabeth Freeman Head First Design Patterns O'Reilly 2004 | ||
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Design Patterns Elements of Reusable Object-Oriented Software Addison-Wesley, 1995 |
Revision as of 21:35, 1 October 2007
Command Pattern
What is Command Pattern?
Command pattern is a design pattern in which you can encapsulate actions/requests as objects and parametrize other objects with different requests. By this way a program (or simply an object) can request actions and that object will not worry how the computation of the request is made. It allows the program to decouple the requester(client) of an action from the object that performs the action(receiver).
Components of Command Pattern
(The following UML diagram is taken from the book Design Patterns Elements of Reusable Object-Oriented Software)
- Command: <<interface>> declares an interface for all commands.
- ConcreteCommand: implements Command interface, defines a binding between a Receiver and an action, and implements execute() method by invoking the corresponding action(s) on Receiver.
- Client: creates a ConcreteCommand object and sets its receiver.
- Invoker: asks the command to carry out the request by calling execute() method of ConcreteCommand.
- Receiver: knows how to perform the operations associated with carrying out a request.
Advantages of Command Pattern
- A command object is a convenient temporary storage for procedure parameters. A command can be set aside for later use.
- As we can save commands we can also use these with data structures, and we can call the actions one after another from a queue with a specific order we want or according to their priorities.
- As it treats the commands as objects, command pattern supports undo-able operations, provided that the operations are stored in a data structure.
- It helps making the code modular.
Uses of Command Pattern
- Command pattern is widely used for saving actions (logging) and for “undo” operations.
- In networking command patterns can be used while passing actions from one computer to another.
- One of its most important area of use is GUI buttons. When a button is pressed a command could be sent to the main program.
Implementations of Command Pattern
We are using command pattern to simulate a fire emergency scenario. In this example, when the fire emergency button is pressed, the fire alarm should be started, the water sprayers should spray water and fire department should be called. When the fire emergency button is depressed, the fire alarm should stop, and water sprayers should stop spraying water.
Java Implementation
In our case, the fire emergency button is the Invoker, and it has no idea what happens when the execute() method is called. FireAlarmOnCommand, FireAlarmOffCommand, WaterSprayerOnCommand, WaterSprayerOffCommand and FireStationCallCommand are ConcreteCommands which implement the Command interface. Their execute() methods invokes the actions on the appropriate Receivers to fulfill the request. FireStation, FireAlarm and WaterSprayer are the Receivers they know how to perform the action requested, in out case they simply print out they they should be doing.
public interface Command { public abstract void execute ( ); } public class FireAlarm { public void turnOn( ) { System.out.println("Fire alarm is on!"); } public void turnOff( ) { System.out.println("Fire alarm is off..."); } } public class FireAlarmOffCommand implements Command { private FireAlarm myAlarm; public FireAlarmOffCommand (FireAlarm a) { myAlarm = a; } public void execute( ) { myAlarm.turnOff( ); } } public class FireAlarmOnCommand implements Command { private FireAlarm myAlarm; public FireAlarmOnCommand (FireAlarm a) { myAlarm = a; } public void execute( ) { myAlarm.turnOn( ); } } public class FireStation { public void call( ) { System.out.println("Fire department is called!"); } } public class FireStationCallCommand implements Command { private FireStation myStation; public FireStationCallCommand (FireStation fs) { myStation = fs; } public void execute() { myStation.call(); } } public class WaterSprayer { public void startSprayWater() { System.out.println("Started spraying water!"); } public void stopSprayWater() { System.out.println("Stopped spraying water..."); } } public class WaterSprayerOffCommand implements Command { private WaterSprayer myWaterSprayer; public WaterSprayerOffCommand (WaterSprayer ws) { myWaterSprayer = ws; } public void execute() { myWaterSprayer.stopSprayWater( ); } } public class WaterSprayerOnCommand implements Command { private WaterSprayer myWaterSprayer; public WaterSprayerOnCommand (WaterSprayer ws) { myWaterSprayer = ws; } public void execute() { myWaterSprayer.startSprayWater( ); } } public class FireEmergencyButton{ private int onCommandCount = 3; private int offCommandCount = 2; private Command [] onCommands; private Command [] offCommands; public FireEmergencyButton(){ onCommands = new Command [onCommandCount]; offCommands = new Command [offCommandCount]; } public void setCommand ( int order, Command on, Command off) { onCommands[order] = on; offCommands[order] = off; } public void setOnCommand ( int order, Command on) { onCommands[order] = on; } void press() { for(int i=0; i< onCommands.length; i++) onCommands[i].execute() ; } void depress() { for(int i=0; i< offCommands.length; i++) offCommands[i].execute ( ); } } public class TestCommand { public static void main(String[] args) { WaterSprayer ws = new WaterSprayer(); WaterSprayerOnCommand wsOn = new WaterSprayerOnCommand (ws); WaterSprayerOffCommand wsOff = new WaterSprayerOffCommand (ws); FireAlarm a = new FireAlarm(); FireAlarmOnCommand alarmOn = new FireAlarmOnCommand (a); FireAlarmOffCommand alarmOff = new FireAlarmOffCommand (a); FireStation fs = new FireStation( ); FireStationCallCommand fsCall = new FireStationCallCommand(fs); FireEmergencyButton feb = new FireEmergencyButton(); feb.setCommand(0, alarmOn, alarmOff); feb.setCommand(1, wsOn, wsOff); feb.setOnCommand(2, fsCall); System.out.println("Fire Emergency Button pressed!"); feb.press(); System.out.println(); System.out.println("Fire Emergency Button depressed!"); feb.depress(); } }
Ruby Implementation
Command Pattern is implemented in Ruby by using Proc objects, a Proc object represents a callable block of code that closes over the variables in scope when it was created. Fire Emergency Button has to sound the alarm, start the water sprayer and call the fire department when it is pressed and it should shut down the alarm, stop the water sprayer when it is depressed. So here in our Ruby implementation, a Fire Emergency Button class takes onCommands and offCommands (which are array of Proc objects) as parameters when it is being initialized and simply calls onCommands when it is pressed and offCommands when it is depressed.
class FireEmergencyButton def initialize(onCommands, offCommands) @onCommands = onCommands @offCommands = offCommands end def press @onCommands.each{|command| command.call} end def depress @offCommands.each{|command| command.call} end end waterSprayOnCommand = proc{puts "Started spraying water!"} waterSprayOffCommand = proc {puts "Stopped spraying water..."} fireAlarmOnCommand = proc{puts "Fire alarm is on!"} fireAlarmOffCommand = proc {puts "Fire alarm is off..."} fireStationCallCommand = proc{puts "Fire department is called!"} onCommands = [] onCommands << fireAlarmOnCommand onCommands << waterSprayOnCommand onCommands << fireStationCallCommand offCommands = [] offCommands << fireAlarmOffCommand offCommands << waterSprayOffCommand feb =FireEmergencyButton.new(onCommands, offCommands) puts "Fire Emergency Button is pressed!" feb.press puts "" puts "Fire Emergency Button is depressed!" feb.depress
Output of Implementations
Both Java and Ruby implementation of the command pattern prints out the following:
Fire Emergency Button pressed! Fire alarm is on! Started spraying water! Fire department is called! Fire Emergency Button depressed! Fire alarm is off... Stopped spraying water...
Comparison of Java and Ruby Implementations
Clarity and Succinctness
- Even though both Java and Ruby code implement the same thing, our Java code is twice as much as longer than our Ruby code. This is basically because the Ruby Proc objects are more concise and convenient than Command objects as implemented in Java.
- On the other hand, Java code is more modular when compared to the Ruby code.
References
- Ruby: Command Pattern
- [Lecture notes provided by Dr. Gehringer on Command Pattern http://courses.ncsu.edu/csc517/common/lectures/notes/lec10.pdf]
- Wikipedia Command Pattern
- Learn How to Implement Command Pattern in Java
- Ruby for the Java World
- Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Design Patterns Elements of Reusable Object-Oriented Software Addison-Wesley, 1995
- Eric Freeman, and Elisabeth Freeman Head First Design Patterns O'Reilly 2004