I'm very new to programming language. My question might not even make sense. My environment is using java and trying to implement both ios and android apps in the same automation testing framework.
So, the idea is that any test script should be able to run on both the apps. Ex: one signin test script should be run for both ios and android.
I've decided to use interface and class implementation approach. The problem I'm facing is with test data. My company doesn't want to use excel. They want to use json for test data.
Here's my problem, look at the following line of code:
ValidBuy goodBuy = JsonFileReader.loadDaTa(TestBase.DATA_PATH, "good-buy.json", ValidBuy.class);
As you can see I have a class "ValidBuy" that has all the getters for a particular json file. I have another class "JsonFileReader" which takes the json filePath, fileName, and a class as an input and returns the data for that class name that I passed in. For this example I've passed ValidBuy.class
So, when I run a positive test, I'm passing "goodBuy" variable which is of type "ValidBuy". The problem starts here.
The test case is now specified with the data from goodBuy because it's type is "ValidBuy" and I'm passing goodBuy as a parameter.
Look at one of my extracted methods:
private void enterBuyInfo(ValidBuy goodBuy) {
itemPage = nativeApp.getItemPage(goodBuy);
itemPage.setItemName(goodBuy.getItemName());
itemPage.setItemSize(goodBuy.getItemSize());
itemPage.setItemDigitSSN(goodBuy.getSsn());
itemPage.clickContinue();
}
You can see those getters I'm using are coming from ValidBuy class.
If I run this test with the data for a badBuy:
InvalidBuy badBuy = JsonFileReader.loadDaTa(TestBase.DATA_PATH, "bad-buy.json", InvalidBuy.class);
It fails because now I have to change "ValidBuy" class with "InvalidBuy" class. Since, changing the parameter in the extracted method in every run is not possible, how can I make it more generic?
I want something like this:
TestData data = JsonFileReader.loadDaTa(RESOURCES_PATH, "good-client.json", InvalidBuy.class);
Here, TestData is generic. It could either be a class or interface (I don't know if that's possible) and the return type will be specified by whichever class I pass into the loadData() method. In this case InvalidBuy.class
The extracted method should look like this:
private void enterBuyInfo(TestData data) {
itemPage = nativeApp.getItemPage(data);
itemPage.setItemName(data.getItemName());
itemPage.setItemSize(data.getItemSize());
itemPage.setItemDigitSSN(data.getSsn());
itemPage.clickContinue();
}
If I can do this, I can use those extracted methods to create more tests.
I know I wrote a lot. I've only tried to make it as clear as possible. If it doesn't make any sense, just disregard it.
Any suggestions, ideas, code samples will be highly appreciated.
Firstly let me see if I understand your question. I think you are saying that loadData may return a value of type ValidBuy or InvalidBuy and you want to pass into it the class that you want returned. You then want to know how to use an interface that might represent either of these classes in your test methods so you can test various return values (both valid and invalid). You use the term "generic" in your question but I'm guessing you don't mean to use it in the specific way it's used in Java.
If I've understood your question correctly, then here's an answer:
Passing the class you wish to have returned into a method is an unusual usage and almost certainly not ideal. Better OOD would be to extract the common methods for all objects returned from loadData into an interface.
So:
interface Buy {
String getItemName();
boolean isValid();
}
class ValidBuy implements Buy {
#Override
public boolean isValid() {
return true;
}
...
}
class InvalidBuy implements Buy {
#Override
public boolean isValid() {
return false;
}
...
}
class JsonFileReader {
Buy loadData(Path path) {
...
}
}
Then your tests can look like:
#Test
void testValidBuy() {
assertTrue(reader.loadData(validPath).isvalid());
}
#Test
void testInvalidBuy() {
assertFalse(reader.loadData(invalidPath).isValid());
}
I realise I've simplified it a bit but hopefully you get the idea.
There is dsl.DefaultExpander and dsl.DefaultExpanderResolver. Design and javadoc gives an idea I can add my custom expander to the flow. But I didn't found real possibility to do that. Do you see how could I achieve DSL to parsed with my custom expander?
Well, in KnowledgeBuilderImpl (the class used to compile DRL/DSL) I see the following method:
public DefaultExpander getDslExpander() {
DefaultExpander expander = new DefaultExpander();
if (this.dslFiles == null || this.dslFiles.isEmpty()) {
return null;
}
for (DSLMappingFile file : this.dslFiles) {
expander.addDSLMapping(file.getMapping());
}
return expander;
}
As you can see, DefaultExpander is hardcoded in there, so I guess there is no way to specify any other implementation.
Same thing happens in DrlParser.getDefaultResolver() where a DefaultExpanderResolver is always instantiated no matters what.
In my opinion, the only way to go is to pre-generate your DRL (outside Drools) based on your own semantics and then to feed the generated DRL to Drools.
Hope it helps,
We are building a product that needs to run on production environments. We need to modify some of the functionality of a existing library. The existing library has class's and methods, we need to override 1 or more methods so that the caller uses our overriden methods instead of the original library.
OriginalLibrary
package com.original.library ;
public class OriginalLibrary {
public int getValue() {
return 1 ;
}
public int getAnotherValue() {
return 1 ;
}
}
Original Client
public class MyClient {
private OriginalLibraryClass originalLibraryObject ;
public MyClient () {
originalLibraryObject = new OriginalLibraryClass() ;
System.out.println(originalLibraryObject.getValue()) ;
System.out.println(originalLibraryObject.getAnotherValue()) ;
}
}
Output
1
2
Now, I need to change getValue() to return 3, instead of 1
Needed Output
3
2
package com.original.library.improved ;
public class OriginalLibrary extends com.original.library.OriginalLibrary {
public int getValue() {
return 3 ;
}
public int getAnotherValue() {
return super.getAnotherValue() ;
}
}
If I do the above, I need to tell my Original Client to reorder and use my new com.original.library.improved jar file before com.original.library.
I am almost convinced that this is the most non intrusive way to launch my improved services over and above the OriginalLibrary. I would have preferred a solution where I need to tell the customer to just add my jar file, no need to recompile, relink your client code.
Similar (not same) questions on a google search
here
here
java assist is excellent library for bytecode manipulation. I have modified code below as per your sample code given, You have to explore javaassist more for your actual requirenment
CtClass etype = ClassPool.getDefault().get("com.original.library.OriginalLibrary");
// get method from class
CtMethod cm = etype.getDeclaredMethod("getValue");
// change the method bosy
cm.setBody("return 3;");
etype.rebuildClassFile();
// give the path where classes is placed, In my eclipse it is bin
etype.writeFile("bin");
OriginalLibrary originalLibraryObject;
originalLibraryObject = new OriginalLibrary();
System.out.println(originalLibraryObject.getValue());
System.out.println(originalLibraryObject.getAnotherValue());
Now output of getValue is 3 because I changed body of that method.
A couple of questions -
How is the client getting an instance of your library's class?
If they are using new OriginalLibrary(), then you're pretty much stuck with creating a new subclass of OriginalLibrary and then asking your client to use your new OriginalLibraryImproved class. This is a common problem encountered in projects and is one reason why a library should not allow its clients to instantiate its classes directly using the new operator.
If instead, your client is instantiating OriginalLibrary using a factory method provided by the library (say, OriginalLibrary.getInstance()), you may want to check if there are any hooks into the factory that allow you to change the object being returned.
Do you have full control of the source code of the original library?
If yes, then you definitely should (and I cannot emphasize this strongly enough) provide factory methods for any class in the library that is instantiable. Doing this allows you to change the actual object being returned without modifying the client (as long as the returned object's class is a subclass of the return value from the factory method).
If not, then I suggest you do the following.
Create a subclass of OriginalLibrary (say, OriginalLibraryImproved).
Create a Factory class named OriginalLibraryFactory that has a static method named getInstance(). Write code to return an instance of OriginalLibraryImproved from this method.
Ask your client to replace all occurrences of new OriginalLibrary() with OriginalLibraryFactory.getInstance(). Note that this approach will only involve adding an extra import for the factory class. The client will still refer to the returned instance using the same OriginalLibrary reference as before.
The advantage of this approach is that it gives you complete flexibility to change the implementation details of OriginalLibraryImproved without affecting the client in anyway. You could also swap OriginalLibararyImproved with a newer version like OriginalLibraryImprovedVer2 and the client will be oblivious to the fact that it is using a new class. You'll just have to make sure that OriginalLibraryImprovedVer2 subclasses OriginalLibrary.
An even more flexible approach is to use the Wrapper or Decorator pattern to avoid the pitfalls of inheritance. You can understand more about the Decorator pattern here.
In a nutshell, try to avoid forcing your clients to use new and try to avoid inheritance unless you have very compelling reasons.
Update: Oracle has confirmed this as a bug.
Summary: Certain custom BeanInfos and PropertyDescriptors that work in JDK 1.6 fail in JDK 1.7, and some only fail after Garbage Collection has run and cleared certain SoftReferences.
Edit: This will also break the ExtendedBeanInfo in Spring 3.1 as noted at the bottom of the post.
Edit: If you invoke sections 7.1 or 8.3 of the JavaBeans spec, explain
exactly where those parts of the spec require anything. The
language is not imperative or normative in those sections. The
language in those sections is that of examples, which are at best
ambiguous as a specification. Furthermore, the BeanInfo API
specifically allows one to change the default behavior, and it is
clearly broken in the second example below.
The Java Beans specification looks for default setter methods with a void return type, but it allows customization of the getter and setter methods through a java.beans.PropertyDescriptor. The simplest way to use it has been to specify the names of the getter and setter.
new PropertyDescriptor("foo", MyClass.class, "getFoo", "setFoo");
This has worked in JDK 1.5 and JDK 1.6 to specify the setter name even when its return type is not void as in the test case below:
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import org.testng.annotations.*;
/**
* Shows what has worked up until JDK 1.7.
*/
public class PropertyDescriptorTest
{
private int i;
public int getI() { return i; }
// A setter that my people call "fluent".
public PropertyDescriptorTest setI(final int i) { this.i = i; return this; }
#Test
public void fluentBeans() throws IntrospectionException
{
// This throws an exception only in JDK 1.7.
final PropertyDescriptor pd = new PropertyDescriptor("i",
PropertyDescriptorTest.class, "getI", "setI");
assert pd.getReadMethod() != null;
assert pd.getWriteMethod() != null;
}
}
The example of custom BeanInfos, which allow the programmatic control of PropertyDescriptors in the Java Beans specification all use void return types for their setters, but nothing in the specification indicates that those examples are normative, and now the behavior of this low-level utility has changed in the new Java classes, which happens to have broken some code on which I am working.
There are numerous changes in in the java.beans package between JDK 1.6 and 1.7, but the one that causes this test to fail appears to be in this diff:
## -240,11 +289,16 ##
}
if (writeMethodName == null) {
- writeMethodName = "set" + getBaseName();
+ writeMethodName = Introspector.SET_PREFIX + getBaseName();
}
- writeMethod = Introspector.findMethod(cls, writeMethodName, 1,
- (type == null) ? null : new Class[] { type });
+ Class[] args = (type == null) ? null : new Class[] { type };
+ writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
+ if (writeMethod != null) {
+ if (!writeMethod.getReturnType().equals(void.class)) {
+ writeMethod = null;
+ }
+ }
try {
setWriteMethod(writeMethod);
} catch (IntrospectionException ex) {
Instead of simply accepting the method with the correct name and parameters, the PropertyDescriptor is now also checking the return type to see whether it is null, so the fluent setter no longer gets used. The PropertyDescriptor throws an IntrospectionException in this case: "Method not found: setI".
However, the problem is much more insidious than the simple test above. Another way to specify the getter and setter methods in the PropertyDescriptor for a custom BeanInfo is to use the actual Method objects:
#Test
public void fluentBeansByMethod()
throws IntrospectionException, NoSuchMethodException
{
final Method readMethod = PropertyDescriptorTest.class.getMethod("getI");
final Method writeMethod = PropertyDescriptorTest.class.getMethod("setI",
Integer.TYPE);
final PropertyDescriptor pd = new PropertyDescriptor("i", readMethod,
writeMethod);
assert pd.getReadMethod() != null;
assert pd.getWriteMethod() != null;
}
Now the above code will pass a unit test in both 1.6 and in 1.7, but the code will begin to fail at some point in time during the life of the JVM instance owing to the very same change that causes the first example to fail immediately. In the second example the only indication that anything has gone wrong comes when trying to use the custom PropertyDescriptor. The setter is null, and most utility code takes that to mean that the property is read-only.
The code in the diff is inside PropertyDescriptor.getWriteMethod(). It executes when the SoftReference holding the actual setter Method is empty. This code is invoked by the PropertyDescriptor constructor in the first example that takes the accessor method names above because initially there is no Method saved in the SoftReferences holding the actual getter and setter.
In the second example the read method and write method are stored in SoftReference objects in the PropertyDescriptor by the constructor, and at first these will contain references to the readMethod and writeMethod getter and setter Methods given to the constructor. If at some point those Soft references are cleared as the Garbage Collector is allowed to do (and it will do), then the getWriteMethod() code will see that the SoftReference gives back null, and it will try to discover the setter. This time, using the same code path inside PropertyDescriptor that causes the first example to fail in JDK 1.7, it will set the write Method to null because the return type is not void. (The return type is not part of a Java method signature.)
Having the behavior change like this over time when using a custom BeanInfo can be extremely confusing. Trying to duplicate the conditions that cause the Garbage Collector to clear those particular SoftReferences is also tedious (though maybe some instrumenting mocking may help.)
The Spring ExtendedBeanInfo class has tests similar to those above. Here is an actual Spring 3.1.1 unit test from ExtendedBeanInfoTest that will pass in unit test mode, but the code being tested will fail in the post-GC insidious mode::
#Test
public void nonStandardWriteMethodOnly() throws IntrospectionException {
#SuppressWarnings("unused") class C {
public C setFoo(String foo) { return this; }
}
BeanInfo bi = Introspector.getBeanInfo(C.class);
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
assertThat(hasReadMethodForProperty(bi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(bi, "foo"), is(false));
assertThat(hasReadMethodForProperty(ebi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(ebi, "foo"), is(true));
}
One suggestion is that we can keep the current code working with the non-void setters by preventing the setter methods from being only softly reachable. That seems like it would work, but that is rather a hack around the changed behavior in JDK 1.7.
Q: Is there some definitive specification stating that non-void setters should be anathema? I've found nothing, and I currently consider this a bug in the JDK 1.7 libraries.
Am I wrong, and why?
Looks like the specification hasn't changed (it requires void setter) but the implementation has been updated to only allow void setters.
Specification:
http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
More specifically see section 7.1 (accessor methods) and 8.3 (design patterns for simple properties)
See some of the later answers in this stackoverflow question:
Does Java bean's setter permit return this?
Section 8.2 specifies:
However, within Java Beans the use of method and type names that match design patterns is entirely optional. If a programmer is prepared to explicitly specify their properties, methods, and events using the BeanInfo interface then they can call their methods and types whatever they like. However, these methods and types will still have to match the required type signatures, as this is essential to their operation.
(emphasis added)
Also, I beleive the method signatures shown in 7.1 and 8.3 are, in fact, normative. They are examples only in the sense that they use "foo" as an example property name.
I would also opt to say disallowing non-void setters is an error. It simply makes fluent programming impossible. Thats why it needs to be be changed.
Since I found Spring 3.1.1 ExtendedBeanInfo unit tests that expect the code not to be broken, and because having the behavior change after garbage collection is obviously a bug, I shall answer this and note the Java bug numbers. The bugs are still not visible on the external database of Java bugs, but I hope that they will become visible at some point:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172854 (Oracle closed this as a duplicate of the bug below since they have the same cause despite different manifestations.)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172865
(The bugs were submitted on May 30, 2012.)
As of June 20, 2012, the bugs are visible in the external database via the links above.
There's something very unsatisfactory about this code:
/*
Given a command string in which the first 8 characters are the command name
padded on the right with whitespace, construct the appropriate kind of
Command object.
*/
public class CommandFactory {
public Command getCommand(String cmd) {
cmdName = cmd.subString(0,8).trim();
if(cmdName.equals("START")) {
return new StartCommand(cmd);
}
if(cmdName.equals("END")) {
return new EndCommand(cmd);
}
// ... more commands in more if blocks here
// else it's a bad command.
return new InvalidCommand(cmd);
}
}
I'm unrepentant about the multiple exit points - the structure is clear. But I'm not happy about the series of near-identical if statements. I've considered making a Map of Strings to Commands:
commandMap = new HashMap();
commandMap.put("START",StartCommand.class);
// ... etc.
... then using Reflection to make instances of the appropriate class looked up from the Map. However while conceptually elegant, this involves a fair amount of Reflection code that whoever inherits this code might not appreciate - although that cost might be offset by the benefits. All the lines hardcoding values into the commandMap smell almost as bad as the if block.
Even better would be if the factory's constructor could scan the classpath for subclasses of Command, query them for String representations, and automatically add them them to its repertoire.
So - how should I go about refactoring this?
I guess some of the frameworks out there give me this kind of thing for free. Let's assume I'm not in a position to migrate this stuff into such a framework.
How about the following code:
public enum CommandFactory {
START {
#Override
Command create(String cmd) {
return new StartCommand(cmd);
}
},
END {
#Override
Command create(String cmd) {
return new EndCommand(cmd);
}
};
abstract Command create(String cmd);
public static Command getCommand(String cmd) {
String cmdName = cmd.substring(0, 8).trim();
CommandFactory factory;
try {
factory = valueOf(cmdName);
}
catch (IllegalArgumentException e) {
return new InvalidCommand(cmd);
}
return factory.create(cmd);
}
}
The valueOf(String) of the enum is used to find the correct factory method. If the factory doesn't exist it will throw an IllegalArgumentException. We can use this as a signal to create the InvalidCommand object.
An extra benefit is that if you can make the method create(String cmd) public if you would also make this way of constructing a Command object compile time checked available to the rest of your code. You could then use CommandFactory.START.create(String cmd) to create a Command object.
The last benefit is that you can easily create a list of all available command in your Javadoc documentation.
Your map of strings to commands I think is good. You could even factor out the string command name to the constructor (i.e. shouldn't StartCommand know that its command is "START"?) If you could do this, instantiation of your command objects is much simpler:
Class c = commandMap.get(cmdName);
if (c != null)
return c.newInstance();
else
throw new IllegalArgumentException(cmdName + " is not as valid command");
Another option is to create an enum of all your commands with links to the classes (assume all your command objects implement CommandInterface):
public enum Command
{
START(StartCommand.class),
END(EndCommand.class);
private Class<? extends CommandInterface> mappedClass;
private Command(Class<? extends CommandInterface> c) { mappedClass = c; }
public CommandInterface getInstance()
{
return mappedClass.newInstance();
}
}
since the toString of an enum is its name, you can use EnumSet to locate the right object and get the class from within.
With the exception of the
cmd.subString(0,8).trim();
part, this doesn't look too bad to me. You could go with the Map and use reflection, but, depending on how often you add/change commands, this might not buy you much.
You should probably document why you only want the first 8 characters, or maybe change the protocol so it's easier to figure out which part of that string is the command (e.g. put a marker like ':' or ';' after the command key-word).
Its not directly an answer to your question, but why don't you throw an InvalidCommandException (or something similar), rather then returning an object of type InvalidCommand?
Unless there is a reason they can't be I always try to make my command implementations stateless. If that's the case you can add a method boolean identifier(String id) method to your command interface which would tell whether this instance could be used for the given string identifier. Then your factory could look something like this (note: I did not compile or test this):
public class CommandFactory {
private static List<Command> commands = new ArrayList<Command>();
public static void registerCommand(Command cmd) {
commands.add(cmd);
}
public Command getCommand(String cmd) {
for(Command instance : commands) {
if(instance.identifier(cmd)) {
return cmd;
}
}
throw new CommandNotRegisteredException(cmd);
}
}
I like your idea, but if you want to avoid reflection you could add instead instances to the HashMap:
commandMap = new HashMap();
commandMap.put("START",new StartCommand());
Whenever you need a command, you just clone it:
command = ((Command) commandMap.get(cmdName)).clone();
And afterwards, you set the command string:
command.setCommandString(cmdName);
But using clone() doesn't sound as elegant as using reflection :(
Taking a Convetion vs Configuration approach and using reflection to scan for available Command objects and loading them into your map would be the way to go. You then have the ability to expose new Commands without a recompile of the factory.
Another approach to dynamically finding the class to load, would be to omit the explicit map, and just try to build the class name from the command string. A title case and concatenate algorithm could turn "START" -> "com.mypackage.commands.StartCommand", and just use reflection to try to instantiate it. Fail somehow (InvalidCommand instance or an Exception of your own) if you can't find the class.
Then you add commands just by adding one object and start using it.
One option would be for each command type to have its own factory. This gives you two advantages:
1) Your generic factory wouldn't call new. So each command type could in future return an object of a different class according to the arguments following the space padding in the string.
2) In your HashMap scheme, you could avoid reflection by, for each command class, mapping to an object implementing a SpecialisedCommandFactory interface, instead of mapping to the class itself. This object in practice would probably be a singleton, but need not be specified as such. Your generic getCommand then calls the specialised getCommand.
That said, factory proliferation can get out of hand, and the code you have is the simplest thing that does the job. Personally I'd probably leave it as it is: you can compare command lists in source and spec without non-local considerations like what might have previously called CommandFactory.registerCommand, or what classes have been discovered through reflection. It's not confusing. It's very unlikely to be slow for less than a thousand commands. The only problem is that you can't add new command types without modifying the factory. But the modification you'd make is simple and repetitive, and if you forget to make it you get an obvious error for command lines containing the new type, so it's not onerous.
Having this repetitive object creation code all hidden in the factory is not so bad. If it has to be done somewhere, at least it's all here, so I'd not worry about it too much.
If you really want to do something about it, maybe go for the Map, but configure it from a properties file, and build the map from that props file.
Without going the classpath discovery route (about which I don't know), you'll always be modifying 2 places: writing a class, and then adding a mapping somewhere (factory, map init, or properties file).
Thinking about this, You could create little instantiation classes, like:
class CreateStartCommands implements CommandCreator {
public bool is_fitting_commandstring(String identifier) {
return identifier == "START"
}
public Startcommand create_instance(cmd) {
return StartCommand(cmd);
}
}
Of course, this adds a whole bunch if tiny classes that can't do much more than say "yes, thats start, give me that" or "nope, don't like that", however, you can now rework the factory to contain a list of those CommandCreators and just ask each of it: "you like this command?" and return the result of create_instance of the first accepting CommandCreator. Of course it now looks kind of akward to extract the first 8 characters outside of the CommandCreator, so I would rework that so you pass the entire command string into the CommandCreator.
I think I applied some "Replace switch with polymorphism"-Refactoring here, in case anyone wonders about that.
I'd go for the map and creation via reflection. If scanning the class path is too slow, you can always add a custom annotation to the class, have an annotation processor running at compile time and store all class names in the jar metadata.
Then, the only mistake you can do is forgetting the annotation.
I did something like this a while ago, using maven and APT.
The way I do it is to not have a generic Factory method.
I like to use Domain Objects as my command objects. Since I use Spring MVC this is a great approach since the DataBinder.setAllowedFields method allows me a great deal of flexibility to use a single domain object for several different forms.
To get a command object, I have a static factory method on the Domain object class. For example, in the member class I'd have methods like -
public static Member getCommandObjectForRegistration();
public static Member getCommandObjectForChangePassword();
And so on.
I'm not sure that this is a great approach, I never saw it suggested anywhere and kind of just came up with it on my own b/c I like the idea of keeping things like this in one place. If anybody sees any reason to object please let me know in the comments...
I would suggest avoiding reflection if at all possible. It is somewhat evil.
You can make your code more concise by using the ternary operator:
return
cmdName.equals("START") ? new StartCommand (cmd) :
cmdName.equals("END" ) ? new EndCommand (cmd) :
new InvalidCommand(cmd);
You could introduce an enum. Making each enum constant a factory is verbose and also has some runtime memory cost. But you can eaily lookup an enum and then use that with == or switch.
import xx.example.Command.*;
Command command = Command.valueOf(commandStr);
return
command == START ? new StartCommand (commandLine) :
command == END ? new EndCommand (commandLine) :
new InvalidCommand(commandLine);
Go with your gut, and reflect. However, in this solution, your Command interface is now assumed to have the setCommandString(String s) method accessible, so that newInstance is easily useable. Also, commandMap is any map with String keys (cmd) to Command class instances that they correspond to.
public class CommandFactory {
public Command getCommand(String cmd) {
if(cmd == null) {
return new InvalidCommand(cmd);
}
Class commandClass = (Class) commandMap.get(cmd);
if(commandClass == null) {
return new InvalidCommand(cmd);
}
try {
Command newCommand = (Command) commandClass.newInstance();
newCommand.setCommandString(cmd);
return newCommand;
}
catch(Exception e) {
return new InvalidCommand(cmd);
}
}
Hmm, browsing, and only just came across this. Can I still comment?
IMHO there's nothing wrong with the original if/else block code. This is simple, and simplicity must always be our first call in design (http://c2.com/cgi/wiki?DoTheSimplestThingThatCouldPossiblyWork)
This seems esp true as all the solutions offered are much less self documenting than the original code...I mean shouldn't we write our code for reading rather than translation...
At the very least, your command should have a getCommandString() -- where StartCommand overrides to return "START". Then you can just register or discover the classes.
+1 on the reflection suggestion, it will give you a more sane structure in your class.
Actually you could do the following (if you haven't thought about it already)
create methods corresponding to the String you'd be expecting as an argument to your getCommand() factory method, then all you have to do is reflect and invoke() these methods and return the correct object.