Visitor パターン
データ構造(Element)と処理(Visitor)の分離を実現。これにCompositeパターンを組み合わせると面白い。
ConcreteVisitorの追加は容易な一方、ConcreteElementの追加は難しい。
ダブルディスパッチ - Wikipediaも関係があるので合わせて読むとよい。
以下の例はwikipediaに載っていたC++のコードをちょいちょいといじったもの。
#include <iostream> #include <vector> using namespace std; //Concrete Elements class Wheel; class Engine; class Body; class Car; //Visitor class Visitor { public: Visitor(){} virtual ~Visitor(){} virtual void Visit(Wheel &) = 0; virtual void Visit(Engine &) = 0; virtual void Visit(Body &) = 0; virtual void Visit(Car &) = 0; }; //Concret Visitor class TestVisitor : public Visitor { public: TestVisitor(){} virtual ~TestVisitor(){} virtual void Visit(Wheel & wheel){ cout << "Visiting Wheel" << endl; } virtual void Visit(Engine & engine){ cout << "Visiting Engine" << endl; } virtual void Visit(Body & body){ cout << "Visiting Body" << endl; } virtual void Visit(Car & car){ cout << "Visiting Car" << endl; } }; //Element class CarElement { public: CarElement(){} virtual ~CarElement(){} virtual void Accept(Visitor &) = 0; }; //Concrete Element 1 class Wheel : public CarElement { public: virtual void Accept(Visitor & visitor) { visitor.Visit(*this); } }; //Concrete Element 2 class Engine : public CarElement { public: virtual void Accept(Visitor & visitor) { visitor.Visit(*this); } }; //Concrete Element 3 class Body : public CarElement { public: Body(int size){ for(int i = 0; i < size; i++){ wheels_.push_back(new Wheel); } } ~Body(){ for(vector<Wheel*>::iterator itr = wheels_.begin(); itr != wheels_.end(); itr++){ delete (*itr); } } virtual void Accept(Visitor & visitor) { visitor.Visit(*this); for (vector<Wheel*>::iterator itr = wheels_.begin(); itr != wheels_.end(); itr++) { (*itr)->Accept(visitor); } } private: vector<Wheel*> wheels_; }; //Concrete Element 4 class Car : public CarElement { public: Car(){ engine_ = new Engine(); body_ = new Body(4); } ~Car(){ delete engine_; delete body_; } virtual void Accept(Visitor & visitor) { visitor.Visit(*this); engine_->Accept(visitor); body_->Accept(visitor); } private: Engine *engine_; Body *body_; }; //main int main() { Car car; TestVisitor visitor; car.Accept(visitor); }