4

I have a suite that can run a few operations with different parameters. The operations and their parameters are provided in an XML config file.

There is a separate class implementing each operation. All of these classes extend an abstract Operation class, so once the class is created it can be handled in the same way in the code, whatever the actual operation is.

However, I do need to create the classes. And so far I see two ways of doing it:

  • a switch statement:

    Operation operation;
    switch (operationName) {
    case "OperationA":
        operation = new OperationA();
        break;
    case "OperationB":
        operation = new OperationB();
        break;
    default:
        log.error("Invalid operation name: " + operationName);
        return true;
    }
    
  • A runtime lookup of a class name. I never tested this option, but it seems to be something like:

    Operation operation = (Operation)Class.forName(operationName).newinstance();
    

The first option seems unwieldy. The second option seems to trust the config too much, though I am not sure about this.

Perhaps I should just verify that operationName is a member of a predefined set or list that contains all my operations (or else set thepossible values in stone in an XML schema and verify the config against it), then use the second option? Or is there something better?

Mikhail Ramendik
  • 1,063
  • 2
  • 12
  • 26
  • *"Perhaps I should just verify that operationName is a member of a predefined set or list that contains all my operations"* - Which is pretty much what the second example will do, because it will throw a series of exceptions if the class can't be loaded, so you end up in the same place, what to do if the configuration tries to do something wrong. Personally, I'd go with the second option, because I'm lazy like that and it allows the greatest level of expansion – MadProgrammer Apr 29 '17 at 00:20
  • This is what polymorphism is for – kourouma_coder Apr 29 '17 at 00:24
  • My worry would be that a malformed config file would put in the name of a valid class that is not an operation class. The cast to Operation should then throw an exception, though? – Mikhail Ramendik Apr 29 '17 at 00:25
  • @kourouma_coder then my question is *how* to use polymorphism to achieve this particular effect? Is my second option the way to do it? – Mikhail Ramendik Apr 29 '17 at 00:26
  • @Mikhail Ramendik, you can for instance, create a method that takes a parameter of type ***your abstract class*** and then inside the method use instanceof to determine the actual type and do the treatment accordingly – kourouma_coder Apr 29 '17 at 00:35
  • 1
    @kourouma_coder my question is about creating the instance. All I have is a string with the name of the operation. After I create the instance, I don't need instanceof - all the handling is done by the methods inside the class. – Mikhail Ramendik Apr 29 '17 at 01:00
  • ok i see, you have some options at your disposal for creating classes dynamically. I think factory method (design pattern ) may be a way – kourouma_coder Apr 29 '17 at 01:16
  • 1
    @kourouma_coder but *within* the factory method, how do I actually create the class, if all I have is a string with the operation name? – Mikhail Ramendik Apr 29 '17 at 02:19

1 Answers1

2

I would prefer to use the second option.

An example class. (Note that the default constructor is required because it is called by .newInstance(). You can also refer to this question: Can I use Class.newInstance() with constructor arguments? if you want to create a new class and use a constructor with parameters.)

package com.mypackage;

public class SomeObject {

    public SomeObject() {}
}

How to create an instance of that class:

try {
    // you need to use the fully qualified name, not just the class name
    SomeObject object = (SomeObject) Class.forName("com.mypackage.SomeObject").newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
    // here you can handle incorrect config in your XML file
}

You can also have a list of qualified names in another configuration file or property and check against that list before attempting to create a class.

Community
  • 1
  • 1
tima
  • 1,498
  • 4
  • 20
  • 28