クライアントアプリケーションで使用できるクラスへの「変換」
public class JimBobStockExchange implements StockLookupService { @Override public int currentPrice(String symbol) { // Jim Bob's real lookup code // goes here... } }
このJimBobStockExchangeクラスはStockLookupServiceインターフェイスを実装しているため、currentPriceメソッドを提供します。この場合、ポートフォリオアプリケーションを作成するのは非常に簡単です。クライアントはPortfolioのインスタンス化に先立ってJimBobStockExchangeのインスタンスを作成するだけで済みます。
StockLookupService service = new JimBobStockExchange(); Portfolio portfolio = new Portfolio(service);
しかし、そんなに都合よく事が運ぶことはめったにありません。多くの場合、ベンダはインターフェイスを提供せず、次のような形になっています。
public class JimBobStockExchange { public int currentPrice(String symbol) { // Jim Bob's real lookup code // goes here... } }
最も簡単な解決策は、JimBobStockExchangeのサブクラスを作成し、そこでStockLookupServiceインターフェイスを実装することです。
public class JimBobStockExchangeAdapter extends JimBobStockExchange implements StockLookupService { @Override public int currentPrice(String symbol) { return super.currentPrice(symbol); } }
このJimBobStockExchangeAdapterクラスは、JimBobStockExchangeクラスのパブリックインターフェイスを、クライアントアプリケーションで使用できるインターフェイスへと「変換」します。これにより、次のように書くことが可能になります。
StockLookupService service = new JimBobStockExchangeAdapter(); Portfolio portfolio = new Portfolio(service);
この変換アダプターのようなしくみをAdapterパターンと呼びます。これはAdapterパターンのごく単純な例です。
場合によっては、もう少し手間がかかることもあります。ベンダがJavaインターフェイスを提供するとしても、それが望みどおりのものだとは限りません。たとえば、サンプルのポートフォリオアプリケーションで、もう1つAntarcticanStockServiceというルックアップサービスをサポートする必要があると仮定しましょう。
import java.math.*; import java.util.*; public class AntarcticanStockService implements StockService { @Override public BigDecimal price(List<String> symbols) { // really cold code here } }
このサービスには常にシンボルのリストを渡す必要があります。また、このサービスは現在の価格をintではなくBigDecimalとして返します。このインターフェイスの「変換」は、1行の委譲では実現できません。
リスト3に、これを実現するアダプタークラスの具体的なコードを示します。この2番目の例では、継承ではなく委譲をベースにしています。
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(); } }
この例でも、アダプタークラスを作成することで、クライアントアプリケーションのコードを単純化できます。
AntarcticanStockServiceAdapter service = new AntarcticanStockServiceAdapter(); Portfolio portfolio = new Portfolio(service);