日曜日, 2月 23, 2014

今更デザインパターン - Visitor

知ってて当然というレベルまで普及した(少なくともGoFの)デザインパターンであるが,中には使用頻度が低いものもある.

使用頻度が低いといってもそれらを知っていて,適切に利用できるかどうかは大きな違いを生むのではないだろうか.

ということでそのようなややFactoryやsingletonに比べてマイナーなデザインパターンをいくつか取り上げる.

Visitor

アルゴリズム及びロジック部分をオブジェクトから切り離す,正に関心の分離を体現するデザインパターンの一つがVisitorである.

あるオブジェクトがロジックを持つのではなく,代わりにvisitorオブジェクトにロジックを持たせる.
そしてそのvisitorオブジェクトを他オブジェクトに訪問(visit)を受け入れ(accept)させて,ロジックをそのオブジェクト内で実行させる.

以下の例はNodeの子クラスにDumpVisitor具象クラスの訪問を受け入れる例である.



#include <iostream>
#include <string>
using namespace std;

class VisitorIF;

class Node {
public:
 virtual void accept(VisitorIF* v) = 0;
};

class FileNode:public Node {
private:
 int m_id;
public:
 FileNode(int id):m_id(id){}
 int GetID() { return m_id; }
 virtual void accept(VisitorIF* v);
};

class DirectoryNode:public Node {
private:
 int m_id;
public:
 DirectoryNode(int id):m_id(id){}
 int GetID() { return m_id; }
 virtual void accept(VisitorIF* v);
};

class VisitorIF {
public:
 virtual void visit(FileNode* n) = 0;
 virtual void visit(DirectoryNode* n) = 0;
};

class DumpVisitor:public VisitorIF {

 virtual void visit(FileNode* n){ cout << "<<FILE>>" << n->GetID() << endl; }
 virtual void visit(DirectoryNode* n){  cout << "<<DIR>>" << n->GetID() << endl; }

};

void FileNode::accept(VisitorIF* v) {

 v->visit(this);

}

void DirectoryNode::accept(VisitorIF* v) {

 v->visit(this);

}

int main() {

 VisitorIF* v = new DumpVisitor();
 FileNode fn(10);
 DirectoryNode dn(20000);
 fn.accept(v);
 dn.accept(v);
 delete v;
}


0 件のコメント: