2012年5月2日水曜日

Visitorパターン

Visitorパターンは、ツリー構造のデータ群(ディレクトリ構造を含めたファイル群みたいな)を処理する際に役立つ設計パターン。別にツリー構造に制限される訳ではないけど、実際それ以外で使わない気がする。

重要な登場人物

Element
データ構造の各要素を表すクラス。ファイルに当たるもの。
ObjectStructure
Elementの集合を扱うクラス。ディレクトリに当たるもの。
Visitor
データ構造の各要素を利用した処理の実装。ElementとObjectStructureに対して行う処理を実装する。


Visitorパターンでは、データ構造の階層の深さを意識することなく、またデータ構造側にデータ処理を一切書くことなく走査を行うことができる。データ走査は、Visitorをroot要素に渡すだけ。あとは勝手にデータ構造を舐め回して各Element(i.e ファイル)へ到達してくれる。


Visitorの実装

各要素に対して処理を行うためのAPIのみを定義した抽象クラスを定義する。

abstract void visit(ObjectStructure aDir);
abstract void visit(Element aFile);

具体的な処理内容に依ってVisitorの継承クラスを実装する。例えば処理内容が「ファイルの名前一覧を作成する」であった場合、FilenameVisitorクラスを作成して、次のような実装を行う。

/**
 * ディレクトリに対して行う処理を定義。
 * @param aDir ObjectStructure
 */
public void visit(ObjectStructure aDir)
{
  for (Element each : aDir.children())
  {
    each.accept(this);
  }
}

/**
 * ファイルに対して行う処理を定義。
 * @param aFile Element
 */
public void visit(Element aFile)
{
  logger.print(aFile.getName());
}

ObjectStructureの実装

Elementの集合を扱うクラスであり、以下のような実装になる。データ処理に関する実装は一切必要ないところがポイント。

/**
 * 子要素のリストを取得する。
 * @return 子要素リスト
 */
public List<Element> children()
{
  return this.children;
}

/**
 * データ処理インターフェースの受け口。
 * @param aVisitor Visitor
 */
public void accept(Visitor aVisitor)
{
  aVisitor.visit(this);
}

Elementの実装

最小の要素を示すクラスであり、以下のような実装になる。これもデータ処理に関する実装は一切必要ない。

/**
 * 名前を取得する。
 * @return 名前
 */
public String getName()
{
  return this.name;
}

/**
 * データ処理インターフェースの受け口。
 * @param aVisitor Visitor
 */
public void accpt(Visitor aVisitor)
{
  aVisitor.visit(this);
}


0 件のコメント:

コメントを投稿