SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

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

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

 最低限の準備が整ったので、Documentオブジェクトを操作する簡単な規則クラスの作成に取りかかります。例えば、Containsクラス(リスト3)は、渡されたキーワードのいずれかが文書に含まれているかどうかを表します。OlderThanクラス(リスト4)は、指定した日付より文書が古いかどうかを判定します。クライアント側から条件を評価できるようにするために、各クラスではExpressionインターフェース(リスト5)を実装しておきます。

リスト3 Contains式
public class Contains implements Expression {
   private final String[] keywords;

   public Contains(String... keywords) {
      this.keywords = keywords;
   }

   @Override
   public boolean evaluate(Document document) {
      return document.contains(keywords);
   }
}
リスト4 OlderThan式
import java.util.*;

public class OlderThan implements Expression {
   private final Date date;

   public OlderThan(Date date) {
      this.date = date;
   }

   @Override
   public boolean evaluate(Document document) {
      return document.getDate().before(date);
   }
}
リスト5 Expressionインターフェース
public interface Expression {
   boolean evaluate(Document document);
}

 Interpreterパターンでは、ContainsやOlderThanのような式のことを「終端式(Terminal Expressions)」と呼びます。終端式は、複合式(「and」や「or」を使用した式)を作るときに基本となる構成要素です。リスト6にAndクラスのテスト、リスト7にAndクラスの実装を示します。

 Andクラスにあるevaluateメソッドのコードが、CompositeパターンとInterpreterパターンで最も重要な部分です。「and」式を評価することで、この式の左側と右側の式がそれぞれ再帰的に評価されます。Interpreterパターンでは、Andのような複合式のことを「非終端式(Nonterminal Expressions)」と呼びます。

リスト6 2つの式から成る非終端式のテスト
import static org.junit.Assert.*;

import java.util.*;
import org.junit.*;

public class AndTest {
   private static final String CONTENTS = "these are the contents";
   private static final Date NOW = new Date();
   private TextDocument document;

   @Before
   public void createDocument() {
      document = new TextDocument(NOW, CONTENTS);
   }

   @Test
   public void failsWhenNeitherConditionMet() {
      Expression expression = new And(new Contains(CONTENTS + "x"),
         new OlderThan(NOW));
      assertFalse(expression.evaluate(document));
   }

   @Test
   public void failsWhenOnlyFirstConditionMet() {
      String text = "contents";
      assertTrue(CONTENTS.indexOf(text) != -1);

      Expression expression = new And(new Contains(text),
         new OlderThan(NOW));
      assertFalse(expression.evaluate(document));
   }

   @Test
   public void passesWhenBothConditionsMet() {
      String text = "contents";
      assertTrue(CONTENTS.indexOf(text) != -1);

      Date future = new Date(NOW.getTime() + 1);

      Expression expression = new And(new Contains(text),
         new OlderThan(future));
      assertTrue(expression.evaluate(document));
   }
}
リスト7 Andクラス
public class And implements Expression {
   private final Expression leftExpression;
   private final Expression rightExpression;

   public And(Expression leftExpression,
      Expression rightExpression) {
         this.leftExpression = leftExpression;
         this.rightExpression = rightExpression;
   }

   public boolean evaluate(Document document) {
      return leftExpression.evaluate(document) &&
         rightExpression.evaluate(document);
   }
}

 Interpreterパターンでは、ExpressionオブジェクトからExpressionオブジェクトに(evaluateメソッド経由で)渡されるDocumentのことを、コンテキストと呼びます。

 Interpreterパターンには多くのメリットがあります。既に見てきたように、個々の式クラスのテストは小さくて分かりやすいですし、とてもすっきりしています。新しい式クラスのセットを文法に組み込むことも簡単で、他の既存の式に影響することはありません。

 Interpreterパターンは、大規模な文法を扱うには不向きです。規模が大きい場合はパーサージェネレータなどの利用を検討すべきです。文法が複雑になると、Interpreterパターンではパフォーマンスに問題が発生したり、使い勝手が著しく落ちたりする可能性があります。

次のページ
解析

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

デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

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/3291 2008/12/02 14:00

イベント

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

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

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

メールバックナンバー