I have this interface:
public interface Command {
T execute(String... args);
}
it works fine for most uses. But when I try to mode
Here's a best-of-multiple-worlds implementation.
// Generic interface for when a client doesn't care
// about the return value of a command.
public interface Command {
// The interfaces themselves take a String[] rather
// than a String... argument, because otherwise the
// implementation of AbstractCommand would be
// more complicated.
public void execute(String[] arguments);
}
// Interface for clients that do need to use the
// return value of a command.
public interface ValuedCommand extends Command {
public T evaluate(String[] arguments);
}
// Optional, but useful if most of your commands are ValuedCommands.
public abstract class AbstractCommand implements ValuedCommand {
public void execute(String[] arguments) {
evaluate(arguments);
}
}
// Singleton class with utility methods.
public class Commands {
private Commands() {} // Singleton class.
// These are useful if you like the vararg calling style.
public static void execute(Command cmd, String... arguments) {
cmd.execute(arguments);
}
public static void execute(ValuedCommand cmd, String... arguments) {
return cmd.evaluate(arguments);
}
// Useful if you have code that requires a ValuedCommand>
// but you only have a plain Command.
public static ValuedCommand> asValuedCommand(Command cmd) {
return new VoidCommand(cmd);
}
private static class VoidCommand extends AbstractCommand {
private final Command cmd;
public VoidCommand(Command actual) {
cmd = actual;
}
public Void evaluate(String[] arguments) {
cmd.execute(arguments);
return null;
}
}
}
With this implementation, clients can talk about a Command
if they don't care about the return value, and a ValuedCommand
if the need a command that returns a certain value.
About the only reason not to go with using Void
straight up is all the unsightly return null;
statements that you will be forced to insert.