November 20, 2014
Hot Topics:

Working With Design Patterns: Adapter

  • February 6, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

The Portfolio example provides a simple example of calling out to an external API. Often, such APIs are not under your control. In this case, the volatility of calling out to a real API, such as the NASDAQ stock exchange, requires you to provide a test double that fixes the price for a couple known shares. The test double allows you to write unit tests that compare against a fixed answer.

Where does the StockLookupService interface come from? Well, sometimes it will be delivered along with the vendor's code. Other times, you'll have to build the interface yourself. Let me first talk about the interface being delivered as part of the API.

public class JimBobStockExchange implements StockLookupService {
   @Override
   public int currentPrice(String symbol) {
      // Jim Bob's real lookup code
      // goes here...
   }
}

Because JimBobStockExchange implements the StockLookupService and thus provides a currentPrice method, life is very easy for the portfolio application. A client needs simply to create an instance of JimBobStockExchange prior to instantiating a Portfolio:

   StockLookupService service = new JimBobStockExchange();
   Portfolio portfolio = new Portfolio(service);

But, things are rarely so convenient. Often, the vendor will provide no interface:

public class JimBobStockExchange {
   public int currentPrice(String symbol) {
      // Jim Bob's real lookup code
      // goes here...
   }
}

The easiest solution is to create a JimBobStockExchange subclass that implements the StockLookupService interface:

public class JimBobStockExchangeAdapter
      extends JimBobStockExchange
      implements StockLookupService {
   @Override
   public int currentPrice(String symbol) {
      return super.currentPrice(symbol);
   }
}

The JimBobStockExchangeAdapter adapts the public interface for the JimBobStockExchange class into an interface that the client application can use:

   StockLookupService service = new JimBobStockExchangeAdapter();
   Portfolio portfolio = new Portfolio(service);

Sometimes, adapters are this simple.

Other times, adapting a public interface is more work. Even if the vendor provides a Java interface, it will not always be the one you want. Suppose your application needs to support a second lookup service, the AntarcticanStockService:

import java.math.*;
import java.util.*;

public class AntarcticanStockService implements StockService {
   @Override
   public BigDecimal price(List<String> symbols) {
      // really cold code here
   }
}

For whatever odd reason, the Antarctican service requires the symbol to be passed as a list. It also returns the current price as a BigDecimal and not an int. Adapting this interface won't be a one-line delegation.

The second adapter example shows how delegation, not inheritance, is the basis for adaptation (see Listing 3).

Listing 3: AntarcticanStockServiceAdapter.

import java.math.*;
import java.util.*;

public class AntarcticanStockServiceAdapter
   implements StockLookupService {
   private AntarcticanStockService service =
      new AntarcticanStockService();

   @Override
   public int currentPrice(String symbol) {
      List<String> symbols = Collections.singletonList(symbol);
      BigDecimal price = service.price(symbols);
      return price.intValue();
   }
}

Creating the adapter again lets your client application code remain simple:

   AntarcticanStockServiceAdapter service =
      new AntarcticanStockServiceAdapter();
   Portfolio portfolio = new Portfolio(service);

Figure 1: Adapter

About the Author

Jeff Langr is a veteran software developer with over a quarter century of professional software development experience. He's written two books, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. Jeff is contributing a chapter to Uncle Bob Martin's upcoming book, Clean Code. Jeff has written over 50 published articles on software development, with more than a couple dozen appearing at Developer.com. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him via email at jeff at langrsoft dot com.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel