問題:
在物件導向系統的開發和設計過程中,經常會遇到一種情況就是需求變更,這樣我們不得不去修改已有的設計,最常見的方法就是在實現好的類添加新的方法去實現客戶新的需求,這樣造成原來的設計根本就不可能封閉;
意圖:
表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
適用環境:
u 一個對象結構包含很多類對象,它們有不同的介面,而你想對這些對象實施一些依賴於其具體類的操作。
u 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“汙染”這些對象的類。Visitor 使得你可以將相關的操作集中起來定義在一個類中。當該對象結構被很多應用共用時,用Visitor 模式讓每個應用僅包含需要用到的操作。
u 定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的介面,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。
結構:
實現:
Element.h檔案
#pragma
once
class
Visitor;
class
Element
{
public:
Element(void);
virtual ~Element(void);
virtual
void Accept(Visitor*vis)=0;
};
class
ConcreteElementA:publicElement
{
public:
ConcreteElementA();
~ConcreteElementA();
void
Accept(Visitor *vis);
};
class
ConcreteElementB:publicElement
{
public:
ConcreteElementB();
~ConcreteElementB();
void
Accept(Visitor *vis);
};
Element.cpp檔案
#include
"StdAfx.h"
#include
"Element.h"
#include
"Visitor.h"
#include
<iostream>
using namespace
std;
Element::Element(void)
{
}
Element::~Element(void)
{
}
void
Element::Accept(Visitor *vis)
{
}
ConcreteElementA::ConcreteElementA()
{
}
ConcreteElementA::~ConcreteElementA()
{
}
void
ConcreteElementA::Accept(Visitor *vis)
{
vis->visitConcreteElementA(this);
cout<<"visitingConcreteElementA...."<<endl;
}
ConcreteElementB::ConcreteElementB()
{
}
ConcreteElementB::~ConcreteElementB()
{
}
void
ConcreteElementB::Accept(Visitor *vis)
{
vis->visitConcreteElementB(this);
cout<<"visitingConcreteElementB...."<<endl;
}
Visitor.h檔案
#pragma
once
class
ConcreteElementA;
class
ConcreteElementA;
class
Element;
class
Visitor
{
public:
Visitor(void);
virtual ~Visitor(void);
virtual
void visitConcreteElementA(Element*elm)=0;
virtual
void visitConcreteElementB(Element*elm)=0;
};
class
ConcreteVisitorA:publicVisitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual
void visitConcreteElementA(Element*elm);
virtual
void visitConcreteElementB(Element*elm);
};
class
ConcreteVisitorB:publicVisitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual
void visitConcreteElementA(Element*elm);
virtual
void visitConcreteElementB(Element*elm);
};
Visitor.cpp檔案
#include
"StdAfx.h"
#include
"Visitor.h"
#include
"Element.h"
#include
<iostream>
using namespace
std;
Visitor::Visitor(void)
{
}
Visitor::~Visitor(void)
{
}
ConcreteVisitorA::ConcreteVisitorA()
{
}
ConcreteVisitorA::~ConcreteVisitorA()
{
}
void
ConcreteVisitorA::visitConcreteElementA(Element *elm)
{
cout<<"iwill visit ConcreteElementA...."<<endl;
}
void
ConcreteVisitorA::visitConcreteElementB(Element *elm)
{
cout<<"iwill visit ConcreteElementB...."<<endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{
}
ConcreteVisitorB::~ConcreteVisitorB()
{
}
void
ConcreteVisitorB::visitConcreteElementA(Element *elm)
{
cout<<"iwill visit ConcreteElementA...."<<endl;
}
void
ConcreteVisitorB::visitConcreteElementB(Element *elm)
{
cout<<"iwill visit ConcreteElementB...."<<endl;
}
調用主函數:
// VisitorPattern.cpp : 定義控制台應用程式的進入點。
//
#include
"stdafx.h"
#include
"Visitor.h"
#include
"Element.h"
#include
<iostream>
using namespace
std;
int _tmain(int
argc, _TCHAR*
argv[])
{
Visitor *vis=new
ConcreteVisitorA();
Element *elm=new
ConcreteElementA();
elm->Accept(vis);
return 0;
}
代碼理解:
在Visitor模式中Accept()操作時一個雙指派的操作。具體調用哪一個具體的Accept()操作,有2個決定因素:1)Element的類型。因為Accept()是多態的操作,需要具
體的Element 類型的子類才可以決定到底調用哪一個 Accept()實現;2)Visitor的類型。
Accept()操作有一個參數(Visitor*vis) ,要決定了實際傳進來的 Visitor 的實體類別才
以決定具體是調用哪個VisitConcrete()實現。