設計模式(23)-行為型模式-VISITOR模式
3.11.1功能
在面向物件系統的開發和設計過程,經常會遇到一種情況就是需求變更(ChangeRequest),經常我們做好的一個設計、實現了一個系統原型,咱們的客戶又會有了新的需求。我們又因此不得不去修改已有的設計,最常見就是解決方案就是給已經設計、實現好的類新增新的方法去實現客戶新的需求,這樣就陷入了設計變更的夢魘:不停地打補丁,其帶來的後果就是設計根本就不可能封閉、編譯永遠都是整個系統程式碼。
Visitor模式則提供了一種解決方案:將更新(變更)封裝到一個類中(Vistor),並由待更改類提供一個接收介面,則可達到效果。
3.11.2 結構圖
• Vi s i t o r(訪問者,如N o d e Vi s i t o r)
— 為該物件結構中C o n c r e t e E l e m e n t的每一個類宣告一個Vi s i t 操作。該操作的名字和特徵標識了傳送Vi s i t 請求給哪個訪問者。
• C o n c r e t e Vi s i t o r(具體訪問者,如 Ty p e C h e c k i ng Vi s i t o r)
— 實現每個由Vi s i t o r 宣告的操作。每個操作實現本演算法的一部分,而該演算法片斷乃是對應於結構中物件的類。
• E l e m e n t(元素,如 N o d e)
— 定義一個Ac c e p t操作,它以一個訪問者為引數。
• C o n c r e t e E l e m e n t(具體元素,如As s i g n m e n t N o d e,Va r i a b l e R e f N o d e)
— 實現Ac c e p t操作,該操作以一個訪問者為引數。
• O b j e c t S t r u c t u r e
— 能列舉它的元素。
— 可以提供一個高層的介面以允許該訪問者訪問它的元素。
— 可以是一個複合(參見C o m p o s i t e(4. 3) )或是一個集合,如一個列表或一個無序集合。
3.11.3 協作
• 一個使用Vi s i t o r 模式的客戶必須建立一個C o n c r e t e Vi s i t o r物件,然後遍歷該物件結構,並用該訪問者訪問每一個元素。
• 當一個元素被訪問時,它呼叫對應於它的類的Vi s i t o r操作。如果必要,該元素將自身作為這個操作的一個引數以便該訪問者訪問它的狀態。
3.11.4 C++程式碼示例
//Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
class ConcreteElementA;
class ConcreteElementB;
class Element;
class Visitor
{
public:
virtual ~Visitor();
virtual void
VisitConcreteElementA(Element* elm) = 0;
virtual void
VisitConcreteElementB(Element* elm) = 0;
protected:
Visitor();
private:
};
class ConcreteVisitorA :public Visitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual void
VisitConcreteElementA(Element* elm);
virtual void
VisitConcreteElementB(Element* elm);
protected:
private:
};
class ConcreteVisitorB :public Visitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual void
VisitConcreteElementA(Element* elm);
virtual void
VisitConcreteElementB(Element* elm);
protected:
private:
};
#endif //~_VISITOR_H_
//Visitor.cpp
#include "Visitor.h"
#include "Element.h"
#include <iostream>
using namespace std;
Visitor::Visitor()
{
}
Visitor::~Visitor()
{
}
ConcreteVisitorA::ConcreteVisitorA()
{
}
ConcreteVisitorA::~ConcreteVisitorA()
{
}
void ConcreteVisitorA::VisitConcreteElementA(Element* elm)
{
cout << "i willvisit ConcreteElementA..."<<endl;
}
void
ConcreteVisitorA::VisitConcreteElementB(Element*elm)
{
cout << "i will visitConcreteElementB..."<<endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{
}
ConcreteVisitorB::~ConcreteVisitorB()
{
}
void ConcreteVisitorB::VisitConcreteElementA(Element* elm)
{
cout << "i will visitConcreteElementA..."<<endl;
}
void ConcreteVisitorB::VisitConcreteElementB(Element* elm)
{
cout << "i will visit ConcreteElementB..."<<endl;
}
//Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
class Visitor;
class Element
{
public:
virtual ~Element();
virtual void Accept(Visitor*vis) = 0;
protected:
Element();
private:
};
class ConcreteElementA :public Element
{
public:
ConcreteElementA();
~ConcreteElementA();
void Accept(Visitor* vis);
protected:
private:
};
class ConcreteElementB :public Element
{
public:
ConcreteElementB();
~ConcreteElementB();
void Accept(Visitor* vis);
protected:
private:
};
#endif //~_ELEMENT_H_
//Element.cpp
#include"Element.h"
#include"Visitor.h"
#include<iostream>
using namespace std;
Element::Element()
{
}
Element::~Element()
{
}
void Element::Accept(Visitor*vis)
{
}
ConcreteElementA::ConcreteElementA()
{
}
ConcreteElementA::~ConcreteElementA()
{
}
void ConcreteElementA::Accept(Visitor* vis)
{
vis->VisitConcreteElementA(this);
cout << "visiting ConcreteElementA..."<<endl;
}
ConcreteElementB::ConcreteElementB()
{
}
ConcreteElementB::~ConcreteElementB()
{
}
void ConcreteElementB::Accept(Visitor* vis)
{
cout << "visiting ConcreteElementB..."<<endl;
vis->VisitConcreteElementB(this);
}
//main.cpp
#include"Element.h"
#include"Visitor.h"
#include<iostream>
using namespace std;
int main(int argc, char*argv[])
{
Visitor* vis = new ConcreteVisitorA();
Element*elm = new
ConcreteElementA();
elm->Accept(vis);
return 0;
}