1.動機
在軟件構件過程中,由于需求的變化,某些類層次結構 中常常需要增加新的行為(方法) ,如果直接在基類中做這樣的更改, 將會給子類帶來很繁重的變更負擔,甚至破壞原有設計 如何在不更改類層次結構的前提下,在運行時根據需要透明地為類層次結構上的各個類動態添加新的操作,從而避免上面的問題?
2.模式定義
定義 :表示一個作用與某對象結構中的各元素的操作功能 :使得可以在不改變(穩定)各元素的類的前提下定義(擴展)作用于這些元素的新操作(變化)結構
3.要點總結
Visitor模式通過所謂的雙重分發 (double dispatch)來實現在不更改(編譯時)Element類層次結構的前提下,在運行時透明地為類層次結構上的各個類動態添加新的操作(支持變化) 所謂雙重分發Visitor模式中間包括了兩個多態分發 第一個為accept方法的多態辨析 第二個為visitElement方法的多態辨析 Visitor模式的最大缺點 在于擴展類層次結構(添加新的Element子類),會導致Visitor類的改變 因此Visitor模式適用于“Element類層次結構穩定,而其中的操作卻經常面臨頻繁改動”
4.代碼感受
1.代碼一
class Visitor ; class Element
{
public : virtual void Func1 ( ) = 0 ; virtual void Func2 ( int data) = 0 ; virtual void Func3 ( int data) = 0 ; virtual ~ Element ( ) { }
} ; class ElementA : public Element
{
public : void Func1 ( ) override { } void Func2 ( int data) override { }
} ; class ElementB : public Element
{
public : void Func1 ( ) override { } void Func2 ( int data) override { }
} ;
2.代碼二
class Visitor ; class Element
{
public : virtual void accept ( Visitor& visitor) = 0 ; virtual ~ Element ( ) { }
} ; class ElementA : public Element
{
public : void accept ( Visitor& visitor) override { visitor. visitElementA ( * this ) ; }
} ; class ElementB : public Element
{
public : void accept ( Visitor& visitor) override { visitor. visitElementB ( * this ) ; }
} ; class Visitor
{
public : virtual void visitElementA ( ElementA& element) = 0 ; virtual void visitElementB ( ElementB& element) = 0 ; virtual ~ Visitor ( ) { }
} ;
class Visitor1 : public Visitor
{
public : void visitElementA ( ElementA& element) override { cout << "Visitor1 is processing ElementA" << endl; } void visitElementB ( ElementB& element) override { cout << "Visitor1 is processing ElementB" << endl; }
} ;
class Visitor2 : public Visitor
{
public : void visitElementA ( ElementA& element) override { cout << "Visitor2 is processing ElementA" << endl; } void visitElementB ( ElementB& element) override { cout << "Visitor2 is processing ElementB" << endl; }
} ; int main ( )
{ Visitor2 visitor; ElementB elementB; elementB. accept ( visitor) ; ElementA elementA; elementA. accept ( visitor) ; return 0 ;
}