インタープリタ デザインパターンの特徴
  インタープリタ デザインパターンは、 Context 役のインスタンスに Expression 役の木構造の中をくぐらせて Context 役の内部状態を加工するためのデザインパターンです。(図参照)。

  図:インタープリタ デザインパターンの構造

  インタープリタ デザインパターンの特徴を以下に示します。

  特徴 | 詳細 | 関連する概念
  --- | --- | ---
  処理の部品化 | 処理を Expression 役インタフェースの実装として部品化することにより、 部品の組み合わせによる再利用を容易にします。 | Strategy
  処理の共通化 | 共通の処理を委譲元で定義し個別の処理を委譲先に委譲することにより、 個別の処理に依存することなく共通の処理を部品化することができます。 | 委譲
  処理の構造化/組み立て/宣言 | 処理部品を組み立てて構造的にオブジェクト指向のデータ構造として宣言することにより、 プログラムを大局的にとらえることができます。 | Composite, 構造化プログラミング, ドメイン特化言語(DSL:Domain Specific Language)
  処理間の依存性の解消 | インタープリタ デザインパターンを使用することにより構造化されたプログラムから各構造間の依存性を解消することができます。 | 委譲、LISPマクロ
  処理の選択・注入 | 処理を構造化する際に結合する処理部品をユーザに選択させることにより、ユーザに対しプログラムを大局的にとらえさせることができます。 | Strategy, DI / IoC
  処理の代理・追加・制限 | 委譲先の処理を代理する処理部品を定義することができます。 | Proxy, Decorator
  オブジェクトの共有 | 委譲先で生成したオブジェクトを保持し、 次のアクセスに対して保持したオブジェクトを再利用する処理部品を定義することができます。 | Flyweight
  横断的な処理の定義 | 業務識別子をまたがった横断的な処理部品を定義することができます。 | AOP
  資源の生成から破棄までの部品化 | 委譲先で使用する資源の生成と破棄を管理する処理部品を定義することができます。 | Before After
  処理の組み合わせの動的な生成 | 処理部品の中で処理部品を生成したり、 処理部品を生成する静的メソッドを定義することにより 処理の組み合わせを動的に生成することができます。 | LISPマクロ
  コンテキストの分離 | Expression 役と Context 役を分離することによりデータの管理が容易になります。 リクエストやスレッドをまたがったデータは Expression 役で定義するのが適しています。 逆にリクエストやスレッド毎のデータは Context 役で管理するのが適しています。 | 構造体 (C言語), カリー化(Currying)
  副作用の局所化・カプセル化・隠蔽 | 副作用が発生する処理を Expression 役実装でカプセル化・隠蔽することにより、 副作用が発生している概念を局所化することができます。 | 調査中
  処理枠組の選択 | Visitor デザインパターンを適用することにより、処理部品の動作定義とは別に、 コンストラクタツリーをデータとみなして操作を定義することができます。 | Visitor, Annotation, Double Dispatch
  揮発性のないデータの注入 | 揮発性のないデータを処理部品で使用する場合、 処理部品内でデータを取得する代わりにコンストラクタ引数で注入することができます。 | DI / IoC, カリー化(Currying)
  例外処理の構造化 | コンストラクタツリーのある箇所で例外が発生した場合、 Java言語の機構によりその例外の処理を行うことが可能なノードに到達するまで 木構造の葉から根に向かって処理が委譲される自然な構造を持ちます。 | Chain of Responsibility
  Web アプリケーションへの適用容易性 | Web アプリケーションはアップストリームとダウンストリームがベースなので、 処理の流れを構造化し横断化することが容易なインタープリタ デザインパターンを適用するのが適しています。 | 調査中

  以上の表より、インタープリタ デザインパターンはその他の多くのデザインパターンと関連していることがわかります。
  インタープリタ デザインパターンを適用する際の注意点と考慮点を以下に示します。

  注意点と考慮点 | 詳細 | 関連する概念
  --- | --- | ---
  高凝集度 | 再利用性を維持するために処理の凝集度が高くなる単位で処理部品を定義する必要があります。 | High Cohesion (GRASP)
  疎結合度 | 再利用性を維持するために処理の結合度が疎になる単位で処理部品を定義する必要があります。 | Low Coupling (GRASP)
  インスタンスの不変性の維持 | 処理部品で扱うデータが参照型で可変の場合、 オブジェクトのコピーをとることによって処理部品の不変性を保証することができます。 | Immutable
  処理を行わない部品 | 処理を行わない処理部品を定義することによりフレームワーク全体が複雑化することを抑止することができます。 | Null Object
  部品群間の接続 | 複数の処理部品を接続するために Adapter デザインパターンを適用することができます。 | Adapter
  処理部品間の連携 | 複数の処理部品の間に同一パラメータなどのコンテキストがある場合、 それらの処理部品を生成するためのクラスを定義することができます。 | Builder
  スレッド別のデータ保持 | ThreadLocal を使用することにより 処理部品の不変性を維持しつつスレッド別でデータを扱うことができます。 | Thread - Specific Storage
  揮発性のあるリソースの生成 | 処理部品の不変性を維持するため、 揮発性のあるリソースを生成するファクトリは複数のスレッドで同時に使用可能である必要があります。 | Abstract Factory, Factory Method, Prototype, Immutable
  処理部品の静的宣言 | Null Object など、業務としてだけでなくフレームワークとして一意な処理部品を静的変数として宣言することにより、 設計の見える化を維持することができます。 | Singleton
  参照キーのカプセル化 | 設計に参照キーが現れた場合はフレームワークの都合によるファンクションポイントが発生している可能性があります。 Thread Specific Strage や Interpreter の適用を検討することにより 参照キーによるバインド処理がカプセル化され、実装の見える化を維持することができます。 (例：org.apache.struts.action.ActionMapping#findForward() や Struts-config.xml の form-bean/@name など) | データモデリング, ファンクションポイント法
  静的型定義/動的型定義の使い分け | フレームワークの設計にはラベリングによるアイデア創発とアイデア伝達のため静的型定義を適用するのが有効です (Woolpack におけるサーバ側値検証とクライアント値検証を比較しました)。 逆にフレームワークと個別業務を接続するためには静的型定義を適用せずに動的型定義のみを適用するのが有効です (業務呼び出しをEL内部クラスとOGNLで比較しました)。 | KJ法(創発技法のひとつ)
  プラグインの構造化 | プラグインによるフレームワーク拡張機構が設計に表れた場合は、 インタープリタ デザインパターン適用を検討することにより拡張機構の構造化を発見することができます。 (メタファ:USBカスケード接続) | Strategy
  ファクトリの構造化 | ファクトリが設計に表れた場合は、 インタープリタ デザインパターンの適用を検討することによりオブジェクト生成の構造化を発見することができます。 | Abstract Factory, DIコンテナ
  XML ファイルによる設定方式の代替 | XML ファイルによる設定が設計に表れた場合は インタープリタ デザインパターン適用を検討することにより、 分割・ DI の横断化・一部ファイル化など設定の柔軟性を維持したり、 処理と設定の混同を防止したりすることができます。 さらに静的型定義言語の場合は早期にエラーを検出することができます。 | ドメイン特化言語(DSL:Domain Specific Language)
  実行/分岐ステップ数(カバレージ)の評価 | コンポジットのツリー宣言は実行されたステップとしてカウントされるため、 見かけ上カバレージが多いように見えます。 カバレージによる品質評価を行う際は注意する必要があります。 | 調査中

トップに戻る
Copyright (C) 2006-2007 Takahiro Nakamura. All rights reserved.