Command Pattern (Invoker returns Command) and constructors
hej,
Using the Command Pattern to run DAOs with a bit of business logic so that I can have a different types of Invoker (Command handler) classes depending if transactions are managed a SLSB or a local test client using JTA. Beyond organizing commands there isn't much hassel with using the Command Pattern to hide DAO implementation (i.e. Hibernate) worked in with minor business logic. However, I am wondering if people have run into problems initializing Receiver objects only by overriding Command constructors just to drive different actions within the execute method? (long winded question but view the example below) For example,
interface Commandextends Serializable{publicvoid execute()}
class CommandHandler{public Command executeHandler(Command command)}
class ConcreateCommandimplements Command{
ConcreateCommand(String xvy){this.xvy=xvy}
ConcreateCommand(Long abc){this.abc=abc}
public ReceiverObject getReceiverObject()
....
execute (){
if (xvy!=null){
....do logic...
}
if (abc!=null){
....do other logic....
}
}
}
Question is really when to stop overloading constructors and use setters instead or stear the execute logic externily another way (maybe even breaking the basic idea of the Command Pattern that clients shouldn't know what goes on under the covers)?
thanks / Matthew
you should create more than one implementation of Command
and maybe a CommandFactory :
class LongCommand implements Command {
Long l;
LongCommand(Long l) {
this.l = l;
}
public void execute() {
// do logic
}
}
class StringCommand implements Command {
String s;
LongCommand(String s) {
this.s = s;
}
public void execute() {
// do other logic
}
}
class CommandFactory {
Command createCommand(Object o) {
if (o instanceof String) {
return new StringCommand((String) o);
}
if (o instanceof Long) {
return new LongCommand((Long) o);
}
throw new IllegalArgumentException(o);
}
}
or even better than using instanceof, create a configuration file :
java.lang.String=StringCommand
java.lang.Long=LongCommand
add a method to Command :
public void setObject(Object o);
and write your factory like this :
class CommandFactory {
private static final Properties configFile = new Properties();
static {
// load configFile here
}
Command createCommand(Object o) { // throws exceptions, didn't bother declaring them
Class argumentClass = o.getClass();
String argumentClassName = argumentClass.getName();
String commandClassName = configFile.getProperty(argumentClassName);
Class commandClass = Class.forName(commandClassName);
Command command = (Command) commandClass.newInstance();
command.setObject(o);
return command;
}
}
so that the implementation of the factory is stable, all that changes is your config file
hth
and of course, l and s should be private attribute members ;-)
hej,
Thanks for the reply. Also looking for why overloading isn't a good idea. Rather than doing what Torajirou is suggesting: extend the super interface of Command into catagorical interfaces (i.e. StringCommand and LongCommand).
In short what is the design problem with overloading? Lack of inheritence? Or?
it's not overloading but overriding
and trust me, it's the right solution
clients shouldn't be aware of the type of command they get, all they should know is that commands can be executed
polymorphism does the rest
that's (partly) what OO is all about
if you're still not convinced, reread description of the command pattern
oh you mean overloading constructors ?
that's not the problem per se
the problem is that you're applying false patterns that bring no benefit to your design
your command's code is spaghetti code cluttered with if-else's and is highly unmaintainable (ever imagined what your execute() method would look like when 100 types of commands exist ? and what's the point in having 99 useless attribute members for each command instance ?)
inheritance and polymorphism helps you get rid of that (if you use the factory I provided), at the cost of (very light) reflection