Java – Best place to convert one object to another object

javaspringtype conversion

I'm writing an interface to bundle two underlying APIs into one new. The APIs provide data about archived invoices.

All three APIs (the two old ones and my new one) have different data structures.
For example: <INVOICE_NO> (old XML), "number" (old JSON), "formatted_number" (new JSON) all mean the same field.

I've created a class for each API and let Spring's RestTemplate handle the parsing/ formatting of the responses.

Now, after receiving a ClassA object from the first API and a ClassB object from the second API, I have to convert them to ClassC objects and return them in it's format.

My first approach was to create two constructors for ClassC which either take an object of type ClassA or an object of type ClassB as argument.

But now, I'm not sure if that's the right thing to do because I'm coupling two data transfer objects.

Would it be better to create an InvoiceConverter class or even something else?

Best Answer

This seems like a perfectly good example of using Adapter Pattern

Basically, you would create one interface that would have one method:

public interface Adapter
{
   ClassC ConvertObject();
}

And then you would create two classes, implementing this interface, like this:

class AdapterClass : Adapter
{
   private ClassA adaptee;
   public AdapterClassA(ClassA pAdaptee)
   {
        adaptee = pAdaptee;
   }

   public ClassC ConvertObject()
   {
      //Code that converts ClassA to ClassC
   }
}

class AdapterClassB : Adapter
{
   private ClassB adaptee;
   public AdapterClassB(ClassB pAdaptee)
   {
        adaptee = pAdaptee;
   }

   public ClassC ConvertObject()
   {
      //Code that converts ClassB to ClassC
   }
}

This way, you are decoupling the logic of type conversion into different classes, leaving the same interface to the user class.

Now, one might raise an issue with unnecessarily creating an interface when nobody but ClassC will invoke the constructor of adapter classes. The interface is not there just because of who will invoke the constructor. For instance, it will be easier to write unit tests if you have something like this.

Next, you might want to decouple the classes completely, and move the invokation of the constructor to some factory class, where ClassC would just see the Adapter interface and then it would not depend on ClassA or ClassB in any way. Of course, this is flirting with the violation of KISS principle, but I would call it a judgment call.

Bottom line is: If you want to decouple ClassC from ClassA and ClassB, there must be something that binds adapter classes. It can be an abstract parent class, or a regular parent class or an interface. Considering that the parent entity carries no information, it is logical to use interface.

Related Topic