LightOn, LightOff, DoorOpen, DoorClose, and DoorLock, respectively. All these classes conveniently implement the Command interface defined below:public interface Command {
public void process();
}
You can write a simple generic launcher in the following way:
public class Launcher{
public static void main(String[] args){
if (args.length>0) {
try {
Command command = (Command)Class.forName(args[0]).newInstance();
command.process();
} catch (Exception ex) {
System.out.println("Invalid command");
}
} else {
System.out.println("Usage: Launcher <command>");
}
}
} // Launcher
You use the Class.forName() method to get a Class object for the class given in a parameter. Then you create an instance of this class using the newInstance() method. Since the class is expected to implement the Command interface, you cast the object into Command, and then call the process() method that will perform the task. If an exception is launched -- due to a misspelling of the class, a wrong name, or a security
exception -- you display an Invalid command message.
You can use the command launcher in the following way:
%java Launcher LightOn
If new tasks are implemented, you don't need to change anything to the launcher. From a programmer point of view, that's great. But what about the user? Suppose a user enters:
%java Launcher OpenDoor Invalid command
Does the Invalid command message mean the user cannot open the door? No, it is simply a name problem (OpenDoor instead of DoorOpen). The user should be able to see a list of available commands. To keep a generic launcher, he or she must be able to find
those commands at runtime.
Java Reflection provides a lot of information about a given class at runtime: you can easily know all its super classes, implemented interfaces, methods, constructors, fields, and so on. But in this case, we are interested in all the classes that implement a given interface. No such information is available via Java Reflection. Before reading Mike Clark's "Java Tip 105: Mastering the Classpath with JWhich," I had no clue how to obtain that information. The remainder of this tip will show you how to apply a process for retrieving information on classes that implement a given interface.
JWhich provides a way to obtain a File object from a package name. Since packages in Java are directories, it is easy to retrieve all the classes contained in a
package using the File object's list() method.
The idea is to check, for each class file in the package, whether or not the corresponding class implements the Command interface using the instanceof statement. This means you can only check each class file's public class, and that the interface and its implementations must
be located in a package.