SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンの使い方

デザインパターンの使い方: Adapter

Adapterパターンについて

  • このエントリーをはてなブックマークに追加

本稿ではデザインパターンのうちの1つ、「Adapterパターン」について解説します。すでに用意されているインターフェースをアプリケーションで使いやすい形に「変換」し、違いを吸収するデザインパターンです。

  • このエントリーをはてなブックマークに追加

Adapterパターンの例

 Portfolioクラスは、ユーザーの株式購入履歴を追跡するアプリケーションの基礎となるものです。当然ながら、ポートフォリオに最も求められる機能は、これらの株式購入の価値を計算することです。

 PortfolioTestクラス(リスト1を参照)は、Portfolioクラスが値を正しく取得できることを検証するのに役立つ単純なスタブの使用例を示しています。Portfolioクラス(リスト2を参照)は、StockLookupServiceインターフェイスを通じて呼び出しを行うことで、各シンボルの価格を取得します。StockLookupServiceのしくみは単純です。このサービスは、株式シンボルが与えられると、そのシンボルの現在のドル価格を返します。StockLookupServiceインターフェイスの定義は次のとおりです。

public interface StockLookupService {
   int currentPrice(String symbol);
}
リスト1 PortfolioTestクラス
import static org.junit.Assert.*;
import org.junit.*;

public class PortfolioTest {
   private static final String MICROSOFT = "MSFT";
   private static final int MICROSOFT_VALUE = 100;
   private static final String IBM = "IBM";
   private static final int IBM_VALUE = 80;

   private Portfolio portfolio;

   @Before
   public void initialize() {
      StockLookupService service = new StockLookupService() {
         @Override
         public int currentPrice(String symbol) {
            if (symbol.equals(MICROSOFT))
               return MICROSOFT_VALUE;
            if (symbol.equals(IBM))
               return IBM_VALUE;
            return 0;
         }
      };

      portfolio = new Portfolio(service);
   }

   @Test
   public void isEmptyOnCreation() {
      assertSize(0);
      assertEquals(0, portfolio.value());
   }

   @Test
   public void storesSharesPerSymbol() {
      portfolio.purchase(MICROSOFT, 2);
      assertSize(1);
      assertEquals(2, portfolio.shares(MICROSOFT));
      assertEquals(2 * MICROSOFT_VALUE, portfolio.value());
   }

   @Test
   public void sumsSharesPurchasedForSameSymbol() {
      portfolio.purchase(MICROSOFT, 1);
      portfolio.purchase(MICROSOFT, 2);
      assertSize(1);
      assertEquals(3, portfolio.shares(MICROSOFT));
      assertEquals(3 * MICROSOFT_VALUE, portfolio.value());
   }

   @Test
   public void segregatesPurchasesBySymbol() {
      portfolio.purchase(MICROSOFT, 5);
      portfolio.purchase(IBM, 10);
      assertSize(2);
      assertEquals(5, portfolio.shares(MICROSOFT));
      assertEquals(10, portfolio.shares(IBM));
      int expectedValue = 5 * MICROSOFT_VALUE + 10 * IBM_VALUE;
      assertEquals(expectedValue, portfolio.value());
   }

   void assertSize(int expected) {
      assertEquals(0 == expected, portfolio.isEmpty());
      assertEquals(expected, portfolio.size());
   }
}
リスト2 Portfolioクラス
import java.util.*;

public class Portfolio {
   private Map<String, Integer> symbols =
      new HashMap<String, Integer>();
   private StockLookupService service;

   public Portfolio(StockLookupService service) {
      this.service = service;
   }

   public boolean isEmpty() {
      return 0 == size();
   }

   public int size() {
      return symbols.size();
   }

   public void purchase(String symbol, int shares) {
      symbols.put(symbol, shares(symbol) + shares);
   }

   public int shares(String symbol) {
      if (!symbols.containsKey(symbol))
         return 0;
      return symbols.get(symbol);
   }

   public int value() {
      int total = 0;
      for (Map.Entry<String, Integer> holding:
         symbols.entrySet()) {
         String symbol = holding.getKey();
         int shares = holding.getValue();
         total += service.currentPrice(symbol) * shares;
      }
      return total;
   }
}

 このPortfolioクラスは、外部APIを呼び出す方法の簡単な例を示しています。通常、このような外部APIは自分の制御下にありません。今回のサンプルでは、NASDAQ証券取引所などの実際のAPIを呼び出す代わりに、いくつかの既知の株式の価格を提供するテストダブル(test double:テスト用の代役の意)を用意する必要があります。このテストダブルにより、決まった「答え」との比較を行う単体テストを書くことができます。

 ところで、StockLookupServiceインターフェイスはどこから来るのでしょうか。ベンダのコードと一緒に提供されることもありますが、自分で作成しなければならないこともあります。まずはAPIの一部として提供されるインターフェイスについて考えてみましょう。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
クライアントアプリケーションで使用できるクラスへの「変換」

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Jeff Langr(Jeff Langr)

本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2817 2008/08/22 15:54

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング