Monday, February 12, 2007

[Tech Tips] Implementing Command Design Pattern via Spring Framework - Part II



The RemoteControl class needs to hold list of supported commands, and needs to delegate request to respective command class base on the pass in command string. Here is the RemoteControl source:

 1
2 package blog.coolboy.springexample.cp;
3
4 import java.util.List;
5 import java.util.HashMap;
6 import blog.coolboy.springexample.cp.command.CommandType;
7 import blog.coolboy.springexample.cp.command.Command;
8
9
10 public class RemoteControl {
11
12 private HashMap<String, Command> supportedCommands = null;
13
14 public RemoteControl() { }
15
16
17 public void setListOfSupportedCommands(List<Command> commandList) {
18 supportedCommands = new HashMap<String, Command>();
19 for(Command cmd : commandList) {
20 supportedCommands.put(
cmd
.getCommandType().getCommandString(),
cmd
);
21 }
22
23 }
24
25 public void execute(String cmdString) {
26 Command cmd = supportedCommands.get(cmdString);
27 if(cmd != null) {
28 cmd.execute();
29 } else {
30 System.out.println("The cmd->" +
cmdString
+ " is not supported!");
31 }
32 }
33
34 }
The RemoteControl will transfer a list of supported commands to internal HashMap using commandString as object key, thus, removing the needs of iterating commands list for each new command execution.

Here's the fun part, we will inject list of supported commands to the RemoteControl above using Spring XML configuration, as shown in code below:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>

<!-- listing of supported Commands here -->

<bean id="tvOnCommand"
class="blog.coolboy.springexample.cp.command.impl.TVOnCommand"/>
<bean id="tvOffCommand"
class
="blog.coolboy.springexample.cp.command.impl.TVOffCommand"/>
<bean id="lightOnCommand"
class="blog.coolboy.springexample.cp.command.impl.LightOnCommand"/>
<bean id="lightOffCommand"
class="blog.coolboy.springexample.cp.command.impl.LightOffCommand"/>

<bean id="remoteControl"
class
="blog.coolboy.springexample.cp.RemoteControl">
<property name="listOfSupportedCommands">
<list>
<ref bean="tvOnCommand"/>
<ref bean="tvOffCommand"/>
<ref bean="lightOnCommand"/>
<ref bean="lightOffCommand"/>
</list>
</property>
</bean>
</beans>


That's all, our remote control class is finished. To roll out new Command, developer just needs to
1. declare the new command type, and it's command string at the CommandType enum
2. implements the command, and
3. inject new command via Spring Configuration.


Here are remoteControlService class to test the remoteControl

 1 package blog.coolboy.springexample.cp;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import org.springframework.context.support.ClassPathXmlApplicationContext;
7 import org.springframework.context.ApplicationContext;
8 import org.springframework.jms.listener.DefaultMessageListenerContainer;
9
10 public class RemoteControlService {
11 public static void main(String [] args) {
12 ApplicationContext context =
new
ClassPathXmlApplicationContext("/conf/remoteControlConfig.xml");
13 RemoteControl remoteControl = (RemoteControl) context.getBean("remoteControl");
14 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
15 System.out.println("Remote Control Ready, enter 'Quit' to terminate the program");
16 String txtCommand;
17 try {
18 do {
19 System.out.print("Enter your command->");
20 txtCommand = reader.readLine();
21 if(txtCommand.equalsIgnoreCase("quit")) {
22 break;
23 } else {
24 remoteControl.execute(txtCommand);
25 }
26 System.out.println("");
27 } while(true);
28 } catch (IOException ex) {
29 ex.printStackTrace();
30 }
31
32 }
33 }
Here are the try run:
------------------

Remote Control Ready, enter 'Quit' to terminate the program
Enter your command->tv.on
Switching On TV
Enter your command->tv.off
Switching off TV
Enter your command->light.on
Turning on Light
Enter your command->light.off
Turning off Light
Enter your command->quit

----------------

Isn't this fun? In the next article, I will explain how I would extends the app to support JMS and SOAP command request, using Spring, stay tune.

No comments: