CSC/ECE 517 Fall 2007/wiki1b 7 c9: Difference between revisions
No edit summary |
|||
(13 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
=Command Pattern= | =Command Pattern= | ||
==Question== | |||
Take a case of the Command pattern and implement it as succinctly as possible in Ruby and Java. Compare the two implementations in terms of clarity and succinctness. The example should be a "real-world" example. While it may be grossly oversimplified for the purpose of illustration, it should not be totally contrived (i.e., should not raise the question, Why would anyone ever want to do that?) | |||
==What is 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). | 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). | ||
Line 15: | Line 18: | ||
*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 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. | *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. | *It helps making the code modular. | ||
In some cases instead of using Command pattern one can use switches. But this is bad design because every time we need to call for an action we need to use switch statements. Furthermore, if we need to change one of the switch cases or write a new case we have to change the code in every switch statement. This is also against the object oriented design of our program because the caller will know how the action it is requesting is implemented. | |||
==Uses of Command Pattern== | ==Uses of Command Pattern== | ||
*Command pattern is widely used for saving actions (logging) and for “undo” operations. | *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. | *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. | *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. | ||
*Also Command pattern could be used when some actions are needed to be called together. This is called a macro and as an example we can give commands saved in an array and calling them when a particular situation invokes them all. | |||
=Implementations of Command Pattern= | =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. | The code presented below for both Java and Ruby are developed by us, and "fire emergency" scenario is our creation. | ||
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 the 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== | ==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 our case they simply print out what they should be doing. | 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 our case they simply print out what they should be doing. | ||
<pre> | <pre> | ||
//interface for all commands. | |||
public interface Command { | public interface Command { | ||
public abstract void execute ( ); | public abstract void execute ( ); | ||
} | } | ||
//represents the fire alarm, has turnOn and turnOff methods. | |||
public class FireAlarm { | public class FireAlarm { | ||
public void turnOn( ) { | public void turnOn( ) { | ||
Line 41: | Line 51: | ||
} | } | ||
//fire alarm off command, implements command and calls the turnOff method of the FireAlarm. | |||
public class FireAlarmOffCommand implements Command { | public class FireAlarmOffCommand implements Command { | ||
private FireAlarm myAlarm; | private FireAlarm myAlarm; | ||
Line 51: | Line 62: | ||
} | } | ||
//fire alarm on command, implements command and calls the turnOn method of the FireAlarm. | |||
public class FireAlarmOnCommand implements Command { | public class FireAlarmOnCommand implements Command { | ||
private FireAlarm myAlarm; | private FireAlarm myAlarm; | ||
Line 61: | Line 73: | ||
} | } | ||
//represents the fire station, has call method. | |||
public class FireStation { | public class FireStation { | ||
public void call( ) { | public void call( ) { | ||
Line 67: | Line 80: | ||
} | } | ||
//fire station call command, implements command and calls the call method of the FireStation. | |||
public class FireStationCallCommand implements Command { | public class FireStationCallCommand implements Command { | ||
private FireStation myStation; | private FireStation myStation; | ||
Line 77: | Line 91: | ||
} | } | ||
//represents water sprayer, has startSprayWater and stopSprayWater methods | |||
public class WaterSprayer { | public class WaterSprayer { | ||
public void startSprayWater() { | public void startSprayWater() { | ||
Line 86: | Line 101: | ||
} | } | ||
//water sprayer off command, implements command and calls the stopSprayWater method of the WaterSprayer. | |||
public class WaterSprayerOffCommand implements Command { | public class WaterSprayerOffCommand implements Command { | ||
private WaterSprayer myWaterSprayer; | private WaterSprayer myWaterSprayer; | ||
Line 96: | Line 112: | ||
} | } | ||
//water sprayer on command, implements command and calls the startSprayWater method of the WaterSprayer. | |||
public class WaterSprayerOnCommand implements Command { | public class WaterSprayerOnCommand implements Command { | ||
private WaterSprayer myWaterSprayer; | private WaterSprayer myWaterSprayer; | ||
Line 106: | Line 123: | ||
} | } | ||
//represents fire emergency button, has onCommands and offCommands, has methods for setting the onCommands and offCommands, and | |||
//executes onCommands when the button is pressed, offCommands when the button is depressed. | |||
import java.util.ArrayList; | |||
public class FireEmergencyButton{ | public class FireEmergencyButton{ | ||
ArrayList <Command> onCommands = new ArrayList <Command>(); | |||
ArrayList <Command> offCommands = new ArrayList <Command>(); | |||
public | public void setCommand (Command on, Command off) { | ||
onCommands.add(on); | |||
offCommands.add(off); | |||
} | } | ||
public void | public void setOnCommand (Command on) { | ||
onCommands.add(on); | |||
} | } | ||
public void | public void press() { | ||
for(Command c : onCommands) | |||
c.execute(); | |||
} | } | ||
public void depress() { | |||
for(Command c : offCommands) | |||
c.execute(); | |||
} | } | ||
} | } | ||
//Test class for testing the command pattern implemented, sets the onCommands and offCommands and simulates what happens when the | |||
//fire emergency button is pressed and depressed. | |||
public class TestCommand { | public class TestCommand { | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
WaterSprayer ws = new WaterSprayer(); | //create water sprayer, create on and off commands for it | ||
WaterSprayer ws = new WaterSprayer( ); | |||
WaterSprayerOnCommand wsOn = new WaterSprayerOnCommand (ws); | |||
WaterSprayerOffCommand wsOff = new WaterSprayerOffCommand (ws); | |||
//create fire alarm, create on and off commands for it | |||
FireAlarm a = new FireAlarm( ); | |||
FireAlarmOnCommand alarmOn = new FireAlarmOnCommand (a); | |||
FireAlarmOffCommand alarmOff = new FireAlarmOffCommand (a); | |||
//create fire station, create call command for it | |||
FireStation fs = new FireStation( ); | |||
FireStationCallCommand fsCall = new FireStationCallCommand(fs); | |||
//create fire emergency button, set its on and off commands | |||
FireEmergencyButton feb = new FireEmergencyButton(); | |||
feb.setCommand(alarmOn, alarmOff); | |||
feb.setCommand(wsOn, wsOff); | |||
feb.setOnCommand(fsCall); | |||
//simulate button pressed | |||
System.out.println("Fire Emergency Button pressed!"); | System.out.println("Fire Emergency Button pressed!"); | ||
feb.press(); | |||
System.out.println("Fire Emergency Button depressed!"); | System.out.println(); | ||
//simulate button depressed | |||
System.out.println("Fire Emergency Button depressed!"); | |||
feb.depress(); | feb.depress(); | ||
} | } | ||
} | } | ||
</pre> | </pre> | ||
Line 162: | Line 188: | ||
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. | 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. | ||
<pre> | <pre> | ||
#represents fire emergency button, has method for setting its on and off commands. | |||
class FireEmergencyButton | class FireEmergencyButton | ||
def initialize(onCommands, offCommands) | def initialize(onCommands, offCommands) | ||
Line 167: | Line 194: | ||
@offCommands = offCommands | @offCommands = offCommands | ||
end | end | ||
#calls onCommands when the button is pressed | |||
def press | def press | ||
@onCommands.each{|command| command.call} | @onCommands.each{|command| command.call} | ||
end | end | ||
#calls offCommands when the button is depressed | |||
def depress | def depress | ||
@offCommands.each{|command| command.call} | @offCommands.each{|command| command.call} | ||
Line 175: | Line 204: | ||
end | end | ||
#defines all the commands for the emergency button | |||
waterSprayOnCommand = proc{puts "Started spraying water!"} | waterSprayOnCommand = proc{puts "Started spraying water!"} | ||
waterSprayOffCommand = proc {puts "Stopped spraying water..."} | waterSprayOffCommand = proc {puts "Stopped spraying water..."} | ||
Line 190: | Line 220: | ||
offCommands << waterSprayOffCommand | offCommands << waterSprayOffCommand | ||
#creates the emergency button | |||
feb =FireEmergencyButton.new(onCommands, offCommands) | feb =FireEmergencyButton.new(onCommands, offCommands) | ||
#simulate button pressed | |||
puts "Fire Emergency Button is pressed!" | puts "Fire Emergency Button is pressed!" | ||
feb.press | feb.press | ||
puts "" | puts "" | ||
#simulate button depressed | |||
puts "Fire Emergency Button is depressed!" | puts "Fire Emergency Button is depressed!" | ||
feb.depress | feb.depress | ||
Line 212: | Line 246: | ||
=Comparison of Java and Ruby Implementations= | =Comparison of Java and Ruby Implementations= | ||
*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. | *Java is more verbose than Ruby. 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. Everything in Java is created within classes and that makes Java code easy to understand especially for unexperienced users. | ||
*In Java an interface declaration is needed to implement a Command pattern whereas in Ruby this is not needed because Ruby has Proc objects built in. | |||
*In Java all the commands need to be defined in classes, Ruby can do this in a single line by using the keyword Proc. | |||
*Ruby's built in iterators makes executing commands from an array a lot more easier. Arraylist in Java has a foreach form to this. | |||
*Adding new commands to our command array at runtime is possible with Ruby. Java is a staticly typed language and meta programming is not possible, thus we can not create and add runtime commands in Java. | |||
As a result we can say that Ruby is more succinct than Java. We can see that implementing a lot of things in Ruby is easier and shorter than Java. But Java being more modular, it makes it easier for someone trying to understand the code written. The results show that experienced users would prefer Ruby for implementing command pattern. | |||
=References= | =References= |
Latest revision as of 05:14, 12 October 2007
Command Pattern
Question
Take a case of the Command pattern and implement it as succinctly as possible in Ruby and Java. Compare the two implementations in terms of clarity and succinctness. The example should be a "real-world" example. While it may be grossly oversimplified for the purpose of illustration, it should not be totally contrived (i.e., should not raise the question, Why would anyone ever want to do that?)
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.
In some cases instead of using Command pattern one can use switches. But this is bad design because every time we need to call for an action we need to use switch statements. Furthermore, if we need to change one of the switch cases or write a new case we have to change the code in every switch statement. This is also against the object oriented design of our program because the caller will know how the action it is requesting is implemented.
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.
- Also Command pattern could be used when some actions are needed to be called together. This is called a macro and as an example we can give commands saved in an array and calling them when a particular situation invokes them all.
Implementations of Command Pattern
The code presented below for both Java and Ruby are developed by us, and "fire emergency" scenario is our creation. 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 the 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 our case they simply print out what they should be doing.
//interface for all commands. public interface Command { public abstract void execute ( ); } //represents the fire alarm, has turnOn and turnOff methods. public class FireAlarm { public void turnOn( ) { System.out.println("Fire alarm is on!"); } public void turnOff( ) { System.out.println("Fire alarm is off..."); } } //fire alarm off command, implements command and calls the turnOff method of the FireAlarm. public class FireAlarmOffCommand implements Command { private FireAlarm myAlarm; public FireAlarmOffCommand (FireAlarm a) { myAlarm = a; } public void execute( ) { myAlarm.turnOff( ); } } //fire alarm on command, implements command and calls the turnOn method of the FireAlarm. public class FireAlarmOnCommand implements Command { private FireAlarm myAlarm; public FireAlarmOnCommand (FireAlarm a) { myAlarm = a; } public void execute( ) { myAlarm.turnOn( ); } } //represents the fire station, has call method. public class FireStation { public void call( ) { System.out.println("Fire department is called!"); } } //fire station call command, implements command and calls the call method of the FireStation. public class FireStationCallCommand implements Command { private FireStation myStation; public FireStationCallCommand (FireStation fs) { myStation = fs; } public void execute() { myStation.call(); } } //represents water sprayer, has startSprayWater and stopSprayWater methods public class WaterSprayer { public void startSprayWater() { System.out.println("Started spraying water!"); } public void stopSprayWater() { System.out.println("Stopped spraying water..."); } } //water sprayer off command, implements command and calls the stopSprayWater method of the WaterSprayer. public class WaterSprayerOffCommand implements Command { private WaterSprayer myWaterSprayer; public WaterSprayerOffCommand (WaterSprayer ws) { myWaterSprayer = ws; } public void execute() { myWaterSprayer.stopSprayWater( ); } } //water sprayer on command, implements command and calls the startSprayWater method of the WaterSprayer. public class WaterSprayerOnCommand implements Command { private WaterSprayer myWaterSprayer; public WaterSprayerOnCommand (WaterSprayer ws) { myWaterSprayer = ws; } public void execute() { myWaterSprayer.startSprayWater( ); } } //represents fire emergency button, has onCommands and offCommands, has methods for setting the onCommands and offCommands, and //executes onCommands when the button is pressed, offCommands when the button is depressed. import java.util.ArrayList; public class FireEmergencyButton{ ArrayList <Command> onCommands = new ArrayList <Command>(); ArrayList <Command> offCommands = new ArrayList <Command>(); public void setCommand (Command on, Command off) { onCommands.add(on); offCommands.add(off); } public void setOnCommand (Command on) { onCommands.add(on); } public void press() { for(Command c : onCommands) c.execute(); } public void depress() { for(Command c : offCommands) c.execute(); } } //Test class for testing the command pattern implemented, sets the onCommands and offCommands and simulates what happens when the //fire emergency button is pressed and depressed. public class TestCommand { public static void main(String[] args) { //create water sprayer, create on and off commands for it WaterSprayer ws = new WaterSprayer( ); WaterSprayerOnCommand wsOn = new WaterSprayerOnCommand (ws); WaterSprayerOffCommand wsOff = new WaterSprayerOffCommand (ws); //create fire alarm, create on and off commands for it FireAlarm a = new FireAlarm( ); FireAlarmOnCommand alarmOn = new FireAlarmOnCommand (a); FireAlarmOffCommand alarmOff = new FireAlarmOffCommand (a); //create fire station, create call command for it FireStation fs = new FireStation( ); FireStationCallCommand fsCall = new FireStationCallCommand(fs); //create fire emergency button, set its on and off commands FireEmergencyButton feb = new FireEmergencyButton(); feb.setCommand(alarmOn, alarmOff); feb.setCommand(wsOn, wsOff); feb.setOnCommand(fsCall); //simulate button pressed System.out.println("Fire Emergency Button pressed!"); feb.press(); System.out.println(); //simulate button depressed 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.
#represents fire emergency button, has method for setting its on and off commands. class FireEmergencyButton def initialize(onCommands, offCommands) @onCommands = onCommands @offCommands = offCommands end #calls onCommands when the button is pressed def press @onCommands.each{|command| command.call} end #calls offCommands when the button is depressed def depress @offCommands.each{|command| command.call} end end #defines all the commands for the emergency button 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 #creates the emergency button feb =FireEmergencyButton.new(onCommands, offCommands) #simulate button pressed puts "Fire Emergency Button is pressed!" feb.press puts "" #simulate button depressed 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
- Java is more verbose than Ruby. 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. Everything in Java is created within classes and that makes Java code easy to understand especially for unexperienced users.
- In Java an interface declaration is needed to implement a Command pattern whereas in Ruby this is not needed because Ruby has Proc objects built in.
- In Java all the commands need to be defined in classes, Ruby can do this in a single line by using the keyword Proc.
- Ruby's built in iterators makes executing commands from an array a lot more easier. Arraylist in Java has a foreach form to this.
- Adding new commands to our command array at runtime is possible with Ruby. Java is a staticly typed language and meta programming is not possible, thus we can not create and add runtime commands in Java.
As a result we can say that Ruby is more succinct than Java. We can see that implementing a lot of things in Ruby is easier and shorter than Java. But Java being more modular, it makes it easier for someone trying to understand the code written. The results show that experienced users would prefer Ruby for implementing command pattern.
References
- Ruby: Command Pattern
- Lecture notes provided by Dr. Gehringer on Command Pattern [1]
- 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