2012年5月2日水曜日

Visitorパターン

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

重要な登場人物

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


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


Visitorの実装

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

  1. abstract void visit(ObjectStructure aDir);  
  2. abstract void visit(Element aFile);  

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

  1. /** 
  2.  * ディレクトリに対して行う処理を定義。 
  3.  * @param aDir ObjectStructure 
  4.  */  
  5. public void visit(ObjectStructure aDir)  
  6. {  
  7.   for (Element each : aDir.children())  
  8.   {  
  9.     each.accept(this);  
  10.   }  
  11. }  
  12.   
  13. /** 
  14.  * ファイルに対して行う処理を定義。 
  15.  * @param aFile Element 
  16.  */  
  17. public void visit(Element aFile)  
  18. {  
  19.   logger.print(aFile.getName());  
  20. }  

ObjectStructureの実装

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

  1. /** 
  2.  * 子要素のリストを取得する。 
  3.  * @return 子要素リスト 
  4.  */  
  5. public List<Element> children()  
  6. {  
  7.   return this.children;  
  8. }  
  9.   
  10. /** 
  11.  * データ処理インターフェースの受け口。 
  12.  * @param aVisitor Visitor 
  13.  */  
  14. public void accept(Visitor aVisitor)  
  15. {  
  16.   aVisitor.visit(this);  
  17. }  

Elementの実装

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

  1. /** 
  2.  * 名前を取得する。 
  3.  * @return 名前 
  4.  */  
  5. public String getName()  
  6. {  
  7.   return this.name;  
  8. }  
  9.   
  10. /** 
  11.  * データ処理インターフェースの受け口。 
  12.  * @param aVisitor Visitor 
  13.  */  
  14. public void accpt(Visitor aVisitor)  
  15. {  
  16.   aVisitor.visit(this);  
  17. }  


0 件のコメント:

コメントを投稿