Adapters in Java 8

adapter

Adapters in Java 8

Let us put ourselves in this situation. You have just bought your brand-new laptop with zillions of cores and its solid state hard drive capable to store the complete catalogue of any platform of online movies. You have been using it at home without any problem, but when you travel you find a problem. I can’t use the laptop because I can’t connect it to the mains of other countries, ¡we don´t have an adapter!

The problem is easily solved, after checking that the power supply works on the margins of voltage from orher countries, you go to the nearest bazaar and you buy the suitable adapter to connect your laptop.

All who have ever worked in applications that involve different teams or use external data, they have been encountered the same situation. My objects in the application domain (my laptop at home) run smoothly. At the time we need to interact with other interfaces, we need to create adapters.

Let us see an adapter example

Let us suppose an application in which we work with financial markets and we have an object to represent the contracts represented by the interface.

public interface ContractInfo {
       public String getContractId();
       public Date getMaturity();
}

To date we have always worked with a market so we only have the implementation.

public class MyMarketContractInfo implements ContractInfo{
       private String contractId;
       private Date maturity;
       /** constructor  */
       public String getContractId(){return contractId;}
       public Date getMaturity(){return maturity;};
}

However after several years we have to receive contracts from other markets and they are received through a closed API where contracts come via the interface.

public interface NewMarketContractInfo {
       public String getSymbolId();
       public Date getEndDate();
}

At the time we see the new interface, we have a moment of panic. How will I be able to work with the new contracts? After you have controled your breathing you realize that with a simple adapter you can read the new contracts without any problem.

public class MyNewMarketContractInfoAdapter implements ContractInfo{
       private NewMarketContractInfo newContract;
       /** constructor  */
       public String getContractId(){return newContract.getSymbolId();}
       public Date getMaturity(){return newContract.getEndDate();}};
}

I have my AC adapter, my laptop operates, when my boss calls me and he tells me “You have to visit each country in the world”.

No, my boss is not so bad, my boss calls me and he tells me “You have to visit at least one country in the world where they have different forms of electric current” and the web page of Wikipedia where they come https://es.wikipedia.org/wiki/Anexo:Enchufes,_voltajes_y_frecuencias_por_pa%C3%ADs

After thanking to myself the opportunity that gives him the opportunity to travel<ironia>off</ironia> I go to the bazaar and I find what I need and that any gadget enthusiast likes. “The universal power adapter”.

Due to the new features of Java 8 such as the default methods in the interfaces and functional programming, it is easier than ever to create power adapters.

Let us go back to our example

My boss calls me and he tells me: “Our platform has to bear the markets of all countries in the world”.

Let us get back to the moment of panic. Do I have to implement an adapter for each market?

Java 8 comes to the rescue

If we add a static method we can convert any object to “ContractInfo”

public interface ContractInfo {
       public String getContractId();
       public Date getMaturity();
       static ContractInfo newInstance(String contractId, Date maturity){
              return new ContractInfo() {
                    @Override
                    public String getContractId() {return contractId;}                
                    @Override
                    public Date getMaturity() {return maturity;}
             };
       }
}

And due to Java 8 we can change a list of contracts quickly.

List<NewMarketContractInfo> newContracts=strangeApi.getNewMarketContracts();
List<ContractInfo> contracts= newContracts.stream()
       .map(p-> ContractInfo.newInstance(p.getSymbolId(),p.getEndDate()))
       .collect(Collectors.toList());

We are so happy with our new adapter when a new market provides us the contracts through an exotic interface.

public interface FunnyContract {
       public String getSymbolId ();
       public int getDay();
       public String getMonth();
       public int getYear();
}

Anyone who has worked in Java with real-time applications will notice that the conversion to Date of the data of this interface can be a little slow. In addition, our application works on a set of contracts that must be filtered. Our filter module works on the ContractInfo surface, so that you can transform the dates of all the contracts even they are going to be filtered can be so unhelpful.

How we delay the switchover until the moment of use?

Java 8 once again to the rescue

static ContractInfo newInstance(Supplier<String> contractId, Supplier<Date> maturity){
       return new ContractInfo() {
              @Override
              public String getContractId() {return contractId.get();}                 
              @Override
              public Date getMaturity() {return maturity.get();}
       };
}

In this way the adapter is created with the method that it must use to convert the data, not the data itself. Somewhere we must have the function

public Date maturityDateFromFunnyContract(FunnyContract c){………}

And to generate our ContractInfo in a “Lazy” way we would do.

List< FunnyContract > newContracts=strangeApi.getNewFunnyContracts();
List<ContractInfo> contracts= newContracts.stream()
       .map(p-> ContractInfo.newInstance(p::getSymbolId,()->this.
              maturityDateFromFunnyContract(p)))
       .collect(Collectors.toList());