設計模式—訪問者模式(二十三)

        軟件領域中的設計模式的重要性不言而喻。設計模式中運用了面向對象編程語言的重要特性:封裝、繼承、多態。雖然知道這些特性的定義但是並沒有做到真正的理解,這樣特性有什麼作用?用於什麼場合中等等問題,帶着疑問開始學習設計模式,主要參考《大話設計模式》和《設計模式:可複用面向對象軟件的基礎》兩本書。

        訪問者模式(Visitor):封裝某些作用於某種數據結構中各元素的操作,它可以在不改變數據結構的前提下定義作用於這些元素的新的操作。

        訪問者模式的目的是要把處理從數據結構分離出來。有比較穩定的數據結構,又有易於變化的算法的話,使用訪問者模式就是比較合適的,因爲訪問者模式使得算法操作的增加變得容易。

        優點:仿問者模式的優點就是增加新的操作很容易,因爲增加新的操作就意味着增加一個新的訪問者。訪問者模式將有關的行爲集中到一個訪問者對象中。

        缺點:使增加新的數據結構變得困難了。


        Visitor ——抽象訪問者

抽象類或者接口,聲明訪問者可以訪問哪些元素,具體到程序匯中就是visit方法的參數定義哪些對象是可以被訪問的。

        ConcreteVisitor——具體訪問者

它影響訪問者訪問到一個類後該怎麼幹,要做什麼事情。

        Element——抽象元素

接口或抽象類,聲明接受哪一類訪問者訪問,程序上是通過accept方法中的參數來定義的。

        ConcreteElement——具體元素

實現accept方法,通常是visitor.visit(this),基本上都形成了一種模式了。

        ObjectStruture——結構對象

元素生產者,一般容納在多個不同類、不同接口的容器。

        訪問者模式其實主要就是讓接口Element及其實現子類負責數據結構的定義,而關於這些數據的操作,則放在訪問者類中,每個訪問者子類可以負責實現一系列相關的涉及不同數據子結構(Element子類型)的操作,而不同的訪問者子類可以定義完全不相關的操作。也就是說訪問者模式的主要作用是把數據結構和作用於結構上的操作解耦合,使得操作集合可以相對自由地演化。這樣訪問者模式的優點就是增加新的操作容易,因爲增加新的操作就意味着增加一個新的訪問者;而訪問者模式的缺點就是增加新的數據結構比較困難。綜上,如果系統有比較穩定的數據結構,又有已於變化的算法的話,使用訪問者模式就比較合適。


例:

#include <iostream>    
#include <vector>
#include <string>    
using namespace std;
class Woman;
class Man;
//抽象行動(抽象觀察者)
class Action{
public:
	virtual void GetManConclusion(Man* concreteElementA) = 0;
	virtual void GetWomanConclusion(Woman* concreteElementB) = 0;	
};
//抽象人類
class Persion{
public:
	virtual void Accept(Action* visitor) = 0;
};
//具體人1 (具體元素1)
class Man :public Persion
{
	virtual void Accept(Action* visitor)
	{
		visitor->GetManConclusion(this);
	}
};
//具體人2 (具體元素2)
class Woman :public Persion
{
	virtual void Accept(Action* visitor)
	{
		visitor->GetWomanConclusion(this);
	}
};
//具體訪問者1
class Success :public Action
{
	virtual void GetManConclusion(Man* concreteElementA)
	{
		cout << "成功男人的背後有一個偉大的女人" << endl;
	}
	virtual void GetWomanConclusion(Woman* concreteElementB)
	{
		cout << "成功女人的背後有一個不成功的男人" << endl;
	}
};
//具體訪問者2
class Failure :public Action
{
	virtual void GetManConclusion(Man* concreteElementA)
	{
		cout << "男人失敗,悶頭喝酒" << endl;
	}
	virtual void GetWomanConclusion(Woman* concreteElementB)
	{
		cout << "女人失敗,兩眼汪汪" << endl;
	}
};
//對象結構類
class ObjectStructure{
private:
	vector<Persion*> elements;
public:
	void AddElement(Persion* element)
	{
		elements.push_back(element);
	}
	void Display(Action* visitor)
	{
		for (Persion* a : elements)
			a->Accept(visitor);
	}
};

int main()
{
	ObjectStructure* o = new ObjectStructure();
	o->AddElement(new Man());
	o->AddElement(new Woman());

	Success* v1 = new Success();
	o->Display(v1);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章