Java Threads mailing list archive

Java Tip 68: Learn how to implement the Command pattern in Java -

From: Rick Beton <rdb@roke.co.uk>
Date: Wed, 10 Feb 1999 09:27:36 +0000

--------------DED2F737D057FE48811C718D
Content-Type: text/plain; charset="us-ascii"

The attached article, from JavaWorld e-zine, proposes a coding style for
passing 'Commands' between active Java objects. Although I've only had
time to skim-read the article, it seems we've been here before!

See http://www.javaworld.com/javatips/jw-javatip68.html?020899txt

Does anyone have the time to write and contribute a similar article,
proposing JCSP multithreaded programming to achieve the same ends? It
would be a technically attractive solution, not least because the
attached article implies a distinction between active and passive
objects, as described by Peter Welch, without actually recognising this
distinction.

A possible approach might be to build on the command object technique as
a means to structure data passing via JCSP channels.

Rick
--
Richard Beton B.Sc. C.Phys. M.Inst.P.
Roke Manor Research Limited (http://www.roke.co.uk/)
--------- Standard Disclaimer about my own views etc etc --------
---------  My mail client accepts rich text (HTML) mail  --------
Welsh Highland Railway: http://www.whr.co.uk/WHR/WHR.html


--------------DED2F737D057FE48811C718D
Content-Disposition: inline;
 filename="jw-javatip68.html"
Content-Base: "http://www.javaworld.com/javatips/jw-j
	avatip68.html?020899txt"
Content-Location: "http://www.javaworld.com/javatips/jw-j
	avatip68.html?020899txt"
Content-Type: text/html; charset="us-ascii"; name="jw-javatip68.html"

<HTML>
<HEAD>
<TITLE>Java Tip 68: Learn how to implement the Command pattern in Java  - JavaWorld - February 1999</TITLE>
<META NAME="description" content="Java Tip 68: Learn how to implement the Command pattern in Java  -- JavaWorld, February 1999">
<META NAME="keywords" content="JavaWorld, Java, Command pattern, callback">
<META NAME="author" content="Bala Paranj">
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" ALINK="#FF0000" VLINK="#551a8b">



<center>
<table width="525" cellpadding="2" border="0">
<tr>
<td colspan="2" align="left" valign="center">
<strong><font size="-1" face="Arial, Helvetica, Sans-serif">
February 1999
</font></strong>
</td> <td align="center" valign="bottom">
 
<IMG width="65" height="20" SRC="/javaworld/icons/javaworld_logo.gif" ALT="JavaWorld">
 
</td> <td colspan="2" align="right" valign="center">
 
<strong><font size="-1" face="Arial, Helvetica, Sans-serif">
<a href="/javaworld/common/jw-subscribe.html?article">Get FREE JW e-mail alerts</A>
</font></strong>
 
</td>
</tr>
<tr>
<td align="center"><a href="/javaworld/jw-02-1999/index.html"><img border="0" width="74" height="21" src="/javaworld/icons/b-home.gif" alt="[JavaWorld Main Page]"></a></td>
<td><a href="/javaworld/search.html"><img border="0" width="107" height="21" src="/javaworld/icons/b-search.gif" alt="[JavaWorld Search]"></a></td>
<td><a href="/javaworld/jw-02-1999/index.html#nuts"><img border="0" width="107" height="21" src="/javaworld/icons/b-nuts2.gif" alt="[Nuts & Bolts]"></a></td>
<td><a href="/javaworld/jw-02-1999/index.html#news"><img border="0" width="107" height="21" src="/javaworld/icons/b-news.gif" alt="[News & Views]"></a></td>
<td><a href="/javaworld/jw-02-1999/index.html#res"><img border="0" width="107" height="21" src="/javaworld/icons/b-jr.gif" alt="[Java Resources]"></a></td>
</tr>
</table>
</center>

<CENTER>
<TABLE CELLPADDING="0" BORDER="0">
<TR>
<TD>
<NOLAYER>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=468x60"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=468x60" width=468 height=60 ></A></IFRAME>
</NOLAYER>
<ilayer id=ph1 visibility=hide width=468 height=60></ilayer>
<BR CLEAR="ALL">
<center>Click on our Sponsors to help Support <em>JavaWorld</em></center>
</TD>
</TR>
</TABLE>
</CENTER><CENTER><IMG SRC="/javaworld/icons/green.gif" HEIGHT="4" WIDTH="468" ALT=""></CENTER>
<H1 ALIGN="CENTER">
Java Tip 68: Learn how to implement the Command pattern in Java 
</H1>
<H3 ALIGN="CENTER">
Add flexibility and extensibility to your programs with this object-oriented equivalent of the callback 
</H3>
<BLOCKQUOTE>
<STRONG>Summary</STRONG><BR>
Sometimes it's necessary to issue requests to objects without knowing
anything about the operation being requested or the receiver of the
request. In procedural languages, this type of communication is
accomplished via a callback: a function that is registered somewhere to
be called at a later point. Commands are the object-oriented equivalent
of callbacks and encapsulate the callback function.  This Java Tip
demonstrates how to implement the Command pattern in Java. 
<em>(1,070 words)</em>

</BLOCKQUOTE>
<CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER><P>
<STRONG>By Bala Paranj</STRONG><P>
<table align="right" cellpadding="0" cellspacing="10" border="0">
<tr><td colspan="2" align="center">
<a href="/javaworld/cgi-bin/jw-mailfriend.cgi?/javaworld/javatips/jw-javatip68.html+Java_Tip_68:_Learn_how_to_implement_the_Command_pattern_in_Java_+Bala_Paranj+nuts"><img border="0" width="31" height="57" src="/javaworld/icons/mailbox2.gif" alt=""></a><br>
<font size="-1" face="Arial, Helvetica, Sans-serif">
<a href="/javaworld/cgi-bin/jw-mailfriend.cgi?/javaworld/javatips/jw-javatip68.html+Java_Tip_68:_Learn_how_to_implement_the_Command_pattern_in_Java_+Bala_Paranj+nuts">Mail this<br> article to<br> a friend</a>

<P>
<TABLE CELLPADDING="0" CELLSPACING="5" BORDER="0">
<TR>
<TD BGCOLOR="000000"><img border="0" width="1" height="1" src="/javaworld/icons/black.gif" alt=""></TD>
<TD>
<font size="-1" face="Arial, Helvetica, Sans-serif">
<center><strong>Supporting<BR>sponsors</strong></center>
<p>
<!-- BEGIN DART 125x125 BANNERS (INTERNET EXPLORER IFRAMES) -->
<NOLAYER>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=1"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125></A></IFRAME>
<P>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=2"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125></A></IFRAME>
<P>
</NOLAYER>
<ilayer id=ph2 visibility=hide height=125 width=125></ilayer>
<P>
<ilayer id=ph3 visibility=hide height=125 width=125></ilayer>
<!-- END DART 125x125 BANNERS (INTERNET EXPLORER IFRAMES) -->
</font>
</TD>
</TR>
</TABLE>
</td></tr></table>

<!-- begin body text -->

<IMG width="29" height="29" ALIGN="LEFT" SRC="/javaworld/abcs/D.gif" ALT="D">esign 
patterns not only accelerate the design phase of an
object-oriented (OO) project but also increase the productivity of the
development team and quality of the software. A <em>Command
pattern</em> is an object behavioral pattern that allows us to achieve
complete decoupling between the sender and the receiver. (A
<em>sender</em> is an object that invokes an operation, and a
<em>receiver</em> is an object that receives the request to execute a
certain operation. With <em>decoupling,</em> the sender has no
knowledge of the <code>Receiver</code>'s interface.) The term
<em>request</em> 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.

<P>
In programming languages like C, <em>function pointers</em> are used to
eliminate giant switch statements. (See 
"<a href="/javaworld/javatips/jw-javatip30.html">Java Tip 30: Polymorphism and Java</a>" for a more detailed description.) Since Java doesn't
have function pointers, we can use the Command pattern to implement
callbacks. You'll see this in action in the first code example below,
called <code>TestCommand.java</code>.

<P>
Developers accustomed to using function pointers in another
language might be tempted to use the <code>Method</code> objects of the
Reflection API in the same way. For example, in his article "Java
Reflection," Paul Tremblett shows you how to use Reflection to 
implement transactions without using switch statements. I've resisted
this temptation, since Sun advises against using the Reflection API 
when other tools more natural to the Java programming language will suffice. 
(See <a href="#resources">Resources</a> for links to Tremblett's article and
for Sun's Reflection tutorial page.) Your program will be easier to debug 
and maintain if you don't use <code>Method</code> objects. Instead, you should 
define an interface and implement it in the classes that perform the 
needed action.

<P>
Therefore, I suggest you use the Command pattern combined with Java's
dynamic loading and binding mechanism to implement function pointers.
(For details on Java's dynamic loading and binding mechanism, see James
Gosling and Henry McGilton's "The Java Language Environment --  A White
Paper," listed in <a href="#resources">Resources</a>.)

<P>
By following the above suggestion, we exploit the polymorphism provided
by the application of a Command pattern to eliminate giant switch
statements, resulting in extensible systems. We also exploit Java's
unique dynamic loading and binding mechanisms to build a
dynamic and dynamically extensible system. This is illustrated in the
second code sample example below, called <code>TestTransactionCommand.java</code>.

<P>
The Command pattern turns the request itself into an object. This
object can be stored and passed around like other objects. The key to
this pattern is a <code>Command</code> interface, which declares an
interface for executing operations. In its simplest form, this
interface includes an abstract <code>execute</code> operation. Each
concrete <code>Command</code> class specifies a receiver-action pair by
storing the <code>Receiver</code> as an instance variable. It provides different
implementations of the <code>execute()</code> method to invoke the
request. The <code>Receiver</code> has the knowledge required to carry
out the request.

<P>
Figure 1 below shows the <code>Switch</code> --  an aggregation of
<code>Command</code> objects. It has <code>flipUp()</code> and
<code>flipDown()</code> operations in its interface.
<code>Switch</code> is called the <em>invoker</em> because it invokes
the execute operation in the command interface.

<P>
The concrete command, <code>LightOnCommand</code>, implements the
<code>execute</code> operation of the command interface. It has the
knowledge to call the appropriate <code>Receiver</code> object's operation. It acts as an adapter in this case. By the term <em>adapter,</em> I mean that the
concrete <code>Command</code> object is a simple connector, connecting
the <code>Invoker</code> and the <code>Receiver</code> with different
interfaces.

<P>
The client instantiates the <code>Invoker</code>,
the <code>Receiver</code>, and the concrete command objects.

<P>
<CENTER>
<TABLE CELLPADDING="5" BORDER="0"><TR><TD>
<CENTER>
<IMG VSPACE="3" WIDTH="425" HEIGHT="192" SRC="/javaworld/jw-02-1999/images/structure.gif">
<BR><FONT SIZE="-1"><STRONG>
</STRONG></FONT></CENTER>
</TD></TR></TABLE>
</CENTER>
Figure 2, the sequence diagram, shows the interactions between the
objects. It illustrates how <code>Command</code> decouples the
<code>Invoker</code> from the <code>Receiver</code> (and the request it
carries out). The client creates a concrete command by parameterizing
its constructor with the appropriate <code>Receiver</code>. Then it
stores the <code>Command</code> in the <code>Invoker</code>. The
<code>Invoker</code> calls back the concrete command, which has the
knowledge to perform the desired <code>Action()</code> operation.

<P>
<CENTER>
<TABLE CELLPADDING="5" BORDER="0"><TR><TD>
<CENTER>
<IMG VSPACE="3" WIDTH="386" HEIGHT="206" SRC="/javaworld/jw-02-1999/images/sequence.gif">
<BR><FONT SIZE="-1"><STRONG>
</STRONG></FONT></CENTER>
</TD></TR></TABLE>
</CENTER>
The client (main program in the listing) creates a concrete
<code>Command</code> object and sets its <code>Receiver</code>. As an
<code>Invoker</code> object, <code>Switch</code> stores the concrete
<code>Command</code> object.  The <code>Invoker</code> issues a request
by calling <code>execute</code> on the <code>Command</code> object. The
concrete <code>Command</code> object invokes operations on its
<code>Receiver</code> to carry out the request.

<P>
The key idea here is that the concrete command registers itself with the <code>Invoker</code> and the <code>Invoker</code> calls it back, executing the command on the <code>Receiver</code>.

<P>
<FONT SIZE="+1"><STRONG>Command pattern example code</STRONG></FONT><BR>
Let's take a look at a simple example illustrating the callback mechanism
achieved via the Command pattern. 

<P>
The example shows a <code>Fan</code> and a <code>Light</code>. Our
objective is to develop a <code>Switch</code> that can turn either 
object on or off. We see that the <code>Fan</code> and the
<code>Light</code> have different interfaces, which means the
<code>Switch</code> has to be independent of the <code>Receiver</code>
interface or it has no knowledge of the code>Receiver</code>'s
interface. To solve this problem, we need to parameterize each of the
<code>Switch</code>s with the appropriate command. Obviously, the
<code>Switch</code> connected to the <code>Light</code> will have a
different command than the <code>Switch</code> connected to the
<code>Fan</code>. The <code>Command</code> class has to be abstract or
an interface for this to work.

<P>
When the constructor for a <code>Switch</code> is invoked, it is
parameterized with the appropriate set of commands. The commands will
be stored as private variables of the <code>Switch</code>.

<P>
When the <code>flipUp()</code> and <code>flipDown()</code>
operations are called, they will simply make the appropriate command to
<code>execute( )</code>. The <code>Switch</code> will have no idea what
happens as a result of <code>execute( )</code> being called.

<P>
<pre>
TestCommand.java

class Fan {
        public void startRotate() {
                System.out.println("Fan is rotating");
        }
        public void stopRotate() {
                System.out.println("Fan is not rotating");
        }
}
class Light {

        public void turnOn( ) {
                System.out.println("Light is on ");
        }
        public void turnOff( ) {
                System.out.println("Light is off");
        }
}
class Switch {
        private Command UpCommand, DownCommand;

        public Switch( Command Up, Command Down) {
                UpCommand = Up; // concrete Command registers itself with the invoker 
                DownCommand = Down;
        }
        void flipUp( ) { // invoker calls back concrete Command, which executes the Command on the receiver 
                        UpCommand . execute ( ) ;							
        }
        void flipDown( ) {
                        DownCommand . execute ( );
        }
}

class LightOnCommand implements Command {

        private Light myLight;

        public LightOnCommand ( Light L) {
                myLight  =  L;
        }
        public void execute( ) {
                myLight . turnOn( );
        }
        
}
class LightOffCommand implements Command {

        private Light myLight;

        public LightOffCommand ( Light L) {
                myLight  =  L;
        }
        public void execute( ) {
                myLight . turnOff( );
        }
        
}
class FanOnCommand implements Command {

        private Fan myFan;

        public FanOnCommand ( Fan F) {
                myFan  =  F;
        }
        public void execute( ) {
                myFan . startRotate( );
        }
        
}
class FanOffCommand implements Command {

        private Fan myFan;

        public FanOffCommand ( Fan F) {
                myFan  =  F;
        }
        public void execute( ) {
                myFan . stopRotate( );
        }
        
}

public class TestCommand {
                public static void main(String[] args) {
                        Light  testLight = new Light( );
                        LightOnCommand testLOC = new LightOnCommand(testLight);
                        LightOffCommand testLFC = new LightOffCommand(testLight);
                        Switch testSwitch = new Switch( testLOC,testLFC);       
                        testSwitch.flipUp( );
                        testSwitch.flipDown( );
                        
                        Fan testFan = new Fan( );
                        FanOnCommand foc = new FanOnCommand(testFan);
                        FanOffCommand ffc = new FanOffCommand(testFan);
                        Switch ts = new Switch( foc,ffc);
                        ts.flipUp( );
                        ts.flipDown( ); 

                }
}               

Command.java

public interface Command {
        public abstract void execute ( );
}
</pre>

<P>
Notice in the code example above that the Command pattern completely
decouples the object that invokes the operation -- <code>(Switch )</code> -- 
from the ones having the knowledge to perform it -- <code>Light</code> and
<code>Fan</code>. This gives us a lot of flexibility: the object issuing
a request must know only how to issue it; it doesn't need to know how
the request will be carried out.

<P>
<FONT SIZE="+1"><STRONG>Command pattern to implement transactions</STRONG></FONT><BR>
A Command pattern is also known as an <em>action</em> or
<em>transaction pattern.</em> Let us consider a server that accepts and
processes transactions delivered by clients via a TCP/IP socket
connection. These transactions consist of a command, followed by zero
or more arguments.

<P>
Developers might use a switch statement with a case for each command.
Usage of <code>Switch</code> statements during coding is a sign of bad
design during the design phase of an object-oriented project. Commands
represent an object-oriented way to support transactions and can be used to solve
this design problem.

<P>
In the client code of the program
<code>TestTransactionCommand.java</code>, all the requests are
encapsulated into the generic <code>TransactionCommand</code> object.
The <code>TransactionCommand</code> constructor is created by the
client and it is registered with the <code>CommandManager</code>. The
queued requests can be executed at different times by calling the
<code>runCommands()</code>, which gives us a lot of
flexibility. It also gives us the  ability to assemble commands into
a composite command. I also have <code>CommandArgument</code>,
<code>CommandReceiver</code>, and <code>CommandManager</code> classes
and subclasses of <code>TransactionCommand</code> -- namely
<code>AddCommand</code> and <code>SubtractCommand</code>. 
Following is a description of each of these classes:

<P>
<ul>
<li><code>CommandArgument</code> is a helper class, which stores the
arguments of the command.  It can be rewritten to simplify the task of
passing a large or variable number of arguments of any type.

<P>
<li><code>CommandReceiver</code> implements all the command-processing
methods and is implemented as a Singleton pattern.

<P>
<li><code>CommandManager</code> is the invoker and is the  <code>Switch</code>
equivalent from the previous example. It stores the generic
<code>TransactionCommand</code> object in its private
<code>myCommand</code> variable. When <code>runCommands( )</code> is
invoked, it calls the <code>execute( )</code> of the appropriate
<code>TransactionCommand</code> object.
</ul>

<P>
In Java, it is possible to look up the definition of a class given a
string containing its name. In the <code>execute ( )</code> operation
of the <code>TransactionCommand</code> class, I compute the class name
and dynamically link it into the running system -- that is, classes are
loaded on the fly as required. I use the naming convention, command
name concatenated by the string "Command" as the name of the
transaction command subclass, so that it can be loaded dynamically.

<P>
Notice that the <code>Class</code> object returned by the
<code>newInstance( )</code> has to be cast to the appropriate type.
This means the new class has to either implement an interface or
subclass an existing class which is known to the program at compile
time. In this case, since we implement the <code>Command</code>
interface, this isn't a problem.

<P>
<pre>
//TestTransactionCommand.java
import java.util.*;

final class CommandReceiver {

  private int[] c;
  private CommandArgument a;
  
     private CommandReceiver(){
       c = new int[2];
     }
   
     private static CommandReceiver cr = new CommandReceiver();
   
     public static CommandReceiver getHandle() {
	 return cr;
     }

     public void setCommandArgument(CommandArgument a) {
	 this.a = a;
     }

     public void methAdd() {
	 c = a.getArguments();
     	 System.out.println("The result is " + (c[0]+c[1]));
     }

     public void methSubtract() {
	 c = a.getArguments();
     	 System.out.println("The result is " + (c[0]-c[1]));
     }
}

 class CommandManager {

   private Command myCommand;

   public CommandManager(Command  myCommand) {
     this.myCommand  =  myCommand ;    
   }

   public void runCommands( ) {
     	    myCommand.execute();     
   }
   
 }

class TransactionCommand implements Command {

  private CommandReceiver commandreceiver;
  private Vector commandnamelist,commandargumentlist; 
  private String commandname;
  private CommandArgument commandargument;
  private Command command;
  
  public TransactionCommand () {
	this(null,null);
  }

  public TransactionCommand ( Vector  commandnamelist, Vector
commandargumentlist){
    this.commandnamelist = commandnamelist;
    this.commandargumentlist = commandargumentlist;
    commandreceiver =  CommandReceiver.getHandle();  
  }
 
  public void execute( ) {

    for (int i = 0; i < commandnamelist.size(); i++) {
     
      commandname = (String)(commandnamelist.get(i));
      commandargument = (CommandArgument)((commandargumentlist.get(i)));
      commandreceiver.setCommandArgument(commandargument);
      String classname = commandname + "Command";
     
         try {
           Class cls = Class.forName(classname);
           command = (Command) cls.newInstance();
         }
         catch (Throwable e) {   
                  System.err.println(e);
         }
      command.execute();
    } 
  }
}

 class AddCommand extends TransactionCommand {
   private CommandReceiver cr;

   public AddCommand () {
      cr = CommandReceiver.getHandle();  
   }  

   public void execute( ) {  
     cr.methAdd();  
   }   
 }

 class SubtractCommand extends TransactionCommand {
   private CommandReceiver cr;
    
   public SubtractCommand () {
      cr = CommandReceiver.getHandle();  
   }

   public void execute( ) {
     cr.methSubtract();
   }   
 }

 class CommandArgument {
   private int[] args;
   
   CommandArgument() {
     args = new int[2];
   }
   public int[] getArguments() {
	return args;
   }
   public void setArgument(int i1, int i2) {
         args[0] = i1; args[1] = i2;
   }
 }
     
 public class TestTransactionCommand {
   private  Vector clist,alist; 
   
   public TestTransactionCommand() {
	 clist = new Vector(); 
       alist = new Vector();
   }

   public void clearBuffer(Vector c, Vector a) {
	 clist.removeAll(c);
       alist.removeAll(a); 
   }

   public Vector getClist() {
	 return clist;
   }

   public Vector getAlist() {
	 return alist;
   }
    
    public static void main(String[] args) {
       CommandArgument ca,ca2;

     TestTransactionCommand t = new TestTransactionCommand();

     ca = new CommandArgument();
     ca.setArgument(2,8);
     Vector myclist = t.getClist();
     Vector myalist = t.getAlist();
     myclist.addElement("Add"); myalist.addElement(ca);

     TransactionCommand tc = new TransactionCommand(myclist,myalist);
     CommandManager cm = new CommandManager(tc);       
                    cm.runCommands();
     
     t.clearBuffer(myclist,myalist);
     ca2 = new CommandArgument();
     ca2.setArgument(5,7);
     myclist = t.getClist();
     myalist = t.getAlist();
     myclist.addElement("Subtract"); myalist.addElement(ca2);
     myclist.addElement("Add"); myalist.addElement(ca2);

     TransactionCommand tc2 = new TransactionCommand(myclist,myalist);        
     CommandManager cm2 = new CommandManager(tc2);       
                    cm2.runCommands();

   }
 }               
</pre>

<P>
The command and its arguments are stored in a list and encapsulated
into the generic <code>TransactionCommand</code> object. The generic
<code>TransactionCommand</code> is registered with the
<code>CommandManager</code>. The commands can be run at any time by
invoking the <code>runCommands()</code> interface in the
<code>CommandManager</code> class.

<P>
The client code doesn't depend on any of the concrete
<code>TransactionCommand</code> subclasses, which means I have
programmed to the interface and not the implementation. This gives us
extensibility: to add a new command, we need to define a new
<code>TransactionCommand</code> subclass and provide the
implementation for the new command-processing method in the
<code>CommandReceiver</code> class. That's all there is to it.

<P>
<FONT SIZE="+1"><STRONG>Conclusion</STRONG></FONT><BR>
The Command pattern has the following advantages: 

<P>
<ol>
<li>A command decouples the object that invokes the operation from the
one that knows how to perform it.

<P>
<li>A command is a first-class object. It can be manipulated and
extended like any other object.

<P>
<li>Commands can be assembled into a composite command.

<P>
<li>It's easy to add new commands, because you don't have to change the
existing classes.
</ol>

<P>
When the sequence of commands executed is saved in a history list, you
can iterate through the list to support undo and redo operations.
You must have an <code>unexecute()</code> operation in the <code>Command</code>
interface to implement this functionality. I will leave this as an
exercise for the reader.

<P>
<EM>Some of this material was inspired by class notes from an 
object-oriented design class given by William E. Fairfield at the 
University of California Santa Cruz Extension.</EM>

<IMG HEIGHT="8" WIDTH="8" SRC="/javaworld/icons/dingbat.gif">
<P>

<!-- end body text -->

<P>
<CENTER><FORM METHOD="POST" ACTION="/javaworld/cgi-bin/jw-nav.cgi">
<SELECT NAME="jump_list">
<option value="http://www.javaworld.com/javaworld/jw-02-1999/index.html">
Also this month in JavaWorld
<option value="http://www.javaworld.com/javaworld/jw-02-1999/index.html#nuts"> 
Nuts & Bolts:
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-javadev.html"> - How to write OpenCard card services for downloading Java
<OPTION VALUE="http://www.javaworld.com/javaworld/javatips/jw-javatip67.html"> - Lazy instantiation 
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-toolbox.html"> - Programming Java threads in the real world, Part 5 
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-internationalize.html"> - Internationalize your software: Part 3
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-enterprise.html"> - Locating CORBA objects using Java IDL
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-techniques.html"> - Design with Runtime Class Information

<option value="http://www.javaworld.com/javaworld/jw-02-1999/index.html#news">
News & Views:
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-bookreview.html"> - In search of the best Java book for beginners
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-newsbriefs.html"> - News and New Product Briefs (11/14/98)
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-idgns-jini.html"> - Sony and others support Sun's Jini
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-idgns-split.html"> - Sun wins bid to keep Java from splitting in two
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-javatv.html"> - Sun announces support for Java TV API for digital interactive TV
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-macworld.html"> - Mac Java news is delivered from the mothership at San Francisco's Macworld Expo
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-jiniconf.html"> - Jini, Sun's Magic Out of the Lamp
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-jinievent.html"> - Jini, Sun's Magic Out of the Lamp
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-macides.html"> - Update on Java development on and for the Mac
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-newsbriefs2.html"> - News and New Product Briefs (1/20/99)
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-iw-xml.html"> - Bluestone moves to marry Java and XML
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-iw-ejb.html"> - Sun spills beans on future EJB releases
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-idgns-inprise.html"> - Discord surfaces in wake of Inprise restructuring
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-letters.html"> - Letters to the Editor
<OPTION VALUE="http://www.javaworld.com/javaworld/jw-02-1999/jw-02-letters2.html"> - Letters to the Editor
</SELECT>
<INPUT TYPE="SUBMIT" VALUE="Go">
</FORM></CENTER>

<CENTER><TABLE CELLPADDING="0" BORDER="0"><TR><TD>
<NOLAYER>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no ><A HREF="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60"><IMG SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60></A></IFRAME>
</NOLAYER>
<ilayer id=ph4 visibility=hide align=center width=468 height=60></ilayer>
</TD></TR></TABLE></CENTER>
<BR>
<CENTER><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR><TD>
<NOLAYER>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=1"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125></A></IFRAME>
</NOLAYER>
<ilayer id=ph5 visibility=hide height=125 width=125></ilayer>
</TD>
<TD>
            
</TD>
<TD>
<NOLAYER>
<IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=2"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125></A></IFRAME>
</NOLAYER>
<ilayer id=ph6 visibility=hide height=125 width=125></ilayer>
</TD></TR></TABLE></CENTER>
<P>
<P>
<CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER>
<P>
<A NAME="resources"><STRONG>Resources</STRONG></A>
<UL>
<LI><em>Design Patterns</em> by Gamma, Helm, Johnson, Vlissides,  Addison-Wesley, 1994, ISBN 0-201-63361-2 <A HREF="http://www.bookbuyer.com/cgi-bin/getTitle.cgi?ISBN=0201633612">http://www.bookbuyer.com/cgi-bin/getTitle.cgi?ISBN=0201633612</A>

<LI><em>Dr. Dobb's Journal,</em> January 1998: "Java Reflection: Not just for tool developers," by Paul Tremblett <A HREF="http://www.ddj.com/articles/1998/9801/9801c/9801c.htm">http://www.ddj.com/articles/1998/9801/9801c/9801c.htm</A>

<LI>Sun's Reflection page<BR>
<A HREF="http://java.sun.com/docs/books/tutorial/reflect/index.html">http://java.sun.com/docs/books/tutorial/reflect/index.html</a>

<LI>"The Java Language Environment --  A White Paper" (May 1996), by James Gosling and Henry McGilton covers details about Java's dynamic loading and binding mechanism<BR>
<A HREF="http://java.sun.com/docs/white/langenv/">http://java.sun.com/docs/white/langenv/</a>

<LI>For more on taking advantage of Java's unique feature of dynamic loading and binding mechanism to build a dynamic and dynamically-extensible system, see<BR>
<A HREF="http://java.sun.com/docs/white/langenv/">http://java.sun.com/docs/white/langenv/</a>

</UL>
<CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER>
<P>
<STRONG>About the author</STRONG><BR>

Bala Paranj is a corporate applications engineer at Mentor Graphics,
Microtec Division. There he resolves complex technical problems of
real-time operating systems, including test case generation, and
research and evaluation of potential solutions. He has a Master of
Science degree in Electrical Engineering from The Wichita State
University, Wichita, Kansas. His research interests include applying
design patterns to solve networking problems, concurrent programming,
and implementation of the solution in Java. When he's not programming,
he enjoys dancing, volleyball, chess, and spending time in nature.
Reach Bala at <A NAME="author" HREF="/javaworld/cgi-bin/jw-mailto.cgi?bala.paranj@javaworld.com+/javaworld/javatips/jw-javatip68.html+author">bala.paranj@javaworld.com</a>.
<BR CLEAR="ALL")

<P>
<FORM METHOD="POST" ACTION="/javaworld/cgi-bin/jw-mini-survey.cgi?1999-jw-javatip68.html">
<a name="mini-ditka">
<strong>What did you think of this article?</strong><br>
</a>

<table width="100%" cellpadding="0" border="0">
<tr> <td align="left" valign="top" rowspan="1" colspan="1">

<INPUT TYPE="radio" NAME="worth" VALUE="3">-Very worth reading<br>
<INPUT TYPE="radio" NAME="worth" VALUE="2">-Worth reading<br>
<INPUT TYPE="radio" NAME="worth" VALUE="1">-Not worth reading<br>

</td> <td align="left" valign="top" rowspan="1" colspan="1">

<INPUT TYPE="radio" NAME="length" VALUE="3">-Too long<br>
<INPUT TYPE="radio" NAME="length" VALUE="2">-Just right<br>
<INPUT TYPE="radio" NAME="length" VALUE="1">-Too short<br>

</td> <td align="left" valign="top" rowspan="1" colspan="1">

<INPUT TYPE="radio" NAME="tech" VALUE="3">-Too technical<br>
<INPUT TYPE="radio" NAME="tech" VALUE="2">-Just right<br>
<INPUT TYPE="radio" NAME="tech" VALUE="1">-Not technical enough<br>

</td>
</tr>
</table>

<table cellpadding="0" border="0">
<tr> <td align="left" valign="top" rowspan="1" colspan="1">

<TEXTAREA NAME="comments" COLS="40" ROWS="3">Comments: </TEXTAREA>

</td> </tr>
<tr> <td align="left" valign="top" rowspan="1" colspan="2">

<TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Name: </TEXTAREA>

</td> </tr>
<tr> <td align="left" valign="top" rowspan="1" colspan="2">

<TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Email: </TEXTAREA>

</td> </tr>
<tr> <td align="left" valign="top" rowspan="1" colspan="1">

<TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Company Name: </TEXTAREA>
    

</td> <td align="left" valign="bottom">

<INPUT TYPE="submit" VALUE="Send data">

</td> </tr> </table>

</FORM>
<P>
<center>
<a href="/javaworld/jw-02-1999/index.html"><img border="0" width="74" height="21" src="/javaworld/icons/b-home.gif" alt="[JavaWorld Main Page]"></a>
<a href="/javaworld/search.html"><img border="0" width="107" height="21" src="/javaworld/icons/b-search.gif" alt="[JavaWorld Search]"></a>
<a href="/javaworld/jw-02-1999/index.html#nuts"><img border="0" width="107" height="21" src="/javaworld/icons/b-nuts2.gif" alt="[Nuts & Bolts]"></a>
<a href="/javaworld/jw-02-1999/index.html#news"><img border="0" width="107" height="21" src="/javaworld/icons/b-news.gif" alt="[News & Views]"></a>
<a href="/javaworld/jw-02-1999/index.html#res"><img border="0" width="107" height="21" src="/javaworld/icons/b-jr.gif" alt="[Java Resources]"></a>
</center>
<P>
<CENTER><A HREF="/javaworld/common/jw-copyright99.html"><IMG BORDER="0" width="338" height="20" SRC="/javaworld/icons/b-copyright99.gif" ALT="[(c) Copyright 1999 Web Publishing Inc., an IDG Communications company]"></A></CENTER>
<P>
If you have problems with this magazine, contact
<A NAME="webmaster" HREF="/javaworld/cgi-bin/jw-mailto.cgi?webmaster@javaworld.com+/javaworld/javatips/jw-javatip68.html+webmaster">webmaster@javaworld.com</A>
<BR>
URL: http://www.javaworld.com/javaworld/javatips/jw-javatip68.html
<BR>
Last modified: Friday, February 05, 1999

<!-- BEGIN DART BANNERS (NETSCAPE LAYERS) -->
<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=468x60" visibility=hide onload="moveToAbsolute(ph1.pageX, ph1.pageY); visibility='show';"></layer>
<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=1" visibility=hide onload="moveToAbsolute(ph2.pageX, ph2.pageY);visibility='show';"></layer>
<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=2" visibility=hide onload="moveToAbsolute(ph3.pageX, ph3.pageY);visibility='show';"></layer>

<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=468x60" visibility=hide onload="moveToAbsolute(ph4.pageX, ph4.pageY); visibility='show';"></layer>
<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=1" visibility=hide onload="moveToAbsolute(ph5.pageX, ph5.pageY);visibility='show';"></layer>
<layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=2" visibility=hide onload="moveToAbsolute(ph6.pageX, ph6.pageY);visibility='show';"></layer>
<!-- END DART BANNERS (NETSCAPE LAYERS) --></BODY>
</HTML>

--------------DED2F737D057FE48811C718D--

	


Last updated: Tue Nov 2 12:11:30 1999
Maintained by Peter Welch.