tags:

views:

391

answers:

4

I have to take over and improve/finish some code that transforms Java objects from a third party library into internal objects. Currently this is done through a big if-else statement along the lines of:

if (obj instanceOf X)
{
    //code to initialize internal object
}
else if (obj instanceOf Y)
{
    //code to initialize different object
}
else if (obj instanceOf Z)
{
    //more init code
}
...

Personally I don't find this solution satisfactory; it's long and messy and to make matters worse many of the if-else blocks contain more if-else blocks dealing with subclasses and edge cases. Is there a better solution to this problem?

+5  A: 

Create an interface like this

public interface Converter<S,T> {
  public T convert(S source);
}

and implement it for each object of X,Y,Z. Then put all known converters into a Map and get happy!

Joachim Sauer
That doesn't really help because generic types are static so you'd still have to do a bunch of instanceof's to use the correct Convert instance.
cletus
You stick the Converters in a Map keyed by its class type.
Steve Kuo
A: 

While it doesn't work for edge cases, building a Map between Classes and Converters

X.getClass() -> X Converter
Y.getClass() -> Y Converter

would get you a lot closer. You'd want to also check superclasses if the leaf class is not found.

Richard Campbell
A: 

Code like this, with all of its instanceof conditions, screams for an interface!

You may want to create a public interface Initializable, with a method public void initialize().

Then all if your if-else's simply resolve into a single obj.initialize() call.

David
A: 

If these internal objects present an interface to the application, rather than being used directly, adapt them rather than converting them.

That is, if you have something like this:

public class ThirdPartyClass { ... }
public interface InternalInterface { ... }
public class InternalClass { ... }

Internal foo(ThirdPartyClass thirdParty) {
    InternalClass internal = new InternalClass();
    // convert thirdPaty -> internal
    return internal;
}

Then instead do something like this:

public class ThirdPartyClass { ... }
public interface InternalInterface { ... }
public class InternalClass { ... }

public class ThirdPartyInternalAdapter implements InternalInterface {
    private final ThirdPartyClass thirdParty;
    public ThirdPartyInternalAdapter(ThirdPartyClass thirdParty) {
        this.thirdParty = thirdParty;
    }
    // implement interface in terms of thirdParty
}

It's not clear from your question if this applies, but if it does this may be easier and more efficient than direct object-to-object conversion.

Alan Krueger