C++設計模式 - 訪問器模式(Visitor)

放飛夢想C發表於2022-03-25

行為變化模式

  • 在元件的構建過程中,元件行為的變化經常導致元件本身劇烈的變化。“行為變化” 模式將元件的行為和元件本身進行解耦,從而支援元件行為的變化,實現兩者之間的鬆耦合。

典型模式

Visitor

動機( Motivation )

  • 在軟體構建過程中,由於需求的改變,某些類層次結構中常常需要增加新的行為(方法) , 如果直接在基類中做這樣的更改,將會給子類帶來很繁重的變更負擔,甚至破壞原有設計。
  • 如何在不更改類層次結構的前提下,在執行時根據需要 透明地為類層次結構.上的各個類動態新增新的操作,從而避免,上述問題?

模式定義

表示一個作用於某物件結構中的各元素的操作。使得可以在不改變(穩定)各元素的類的前提下定義(擴充套件)作用於這些元素的新操作(變化)。

結構

在這裡插入圖片描述

要點總結

  • Visito:模式通過所謂雙重分發(double dispath )來實現在不更改,(不新增新的操作-編譯時)Elemen類層次結構的前提下在執行時透明地為類層次結構上的各個類動態添和新的操作(支援變化)。
  • 所謂雙重分發即Visitor模式中間包括了兩個多型分發(注意其中的多型機制):第一個為accept方法的多型 辨析;第二個為visitElementX方法的多型辨析
  • Visito模式最大缺點在於擴充套件類層次結構(增添新的Element子類)會導致Visito類的改變。因此Visito模式適用於Element類層次結構穩定,而其中的操作卻經常面臨頻繁改動。

cpp

#include<iostream>
using namespace std;

class Visitor;
class Element {
public:
	virtual void accept(Visitor& visitor) = 0;//第一次多型辨析(找accept)
	virtual ~Element() {}
};
class ElementA :public Element {
public:
	virtual void accept(Visitor& visitor) override; //第二次多型辨析(找visitElementA)
};
class ElementB :public Element {
public:
	void accept(Visitor& visitor) override;
};

class Visitor {
public:
	virtual void visitElementA(ElementA& element) = 0;
	virtual void visitElementB(ElementB& element) = 0;
	virtual ~Visitor() {}
};

void ElementA::accept(Visitor& visitor) {
	visitor.visitElementA(*this);//第二次多型辨析(找visitElementA)
}
void ElementB::accept(Visitor& visitor) {
	visitor.visitElementB(*this);
}
//=================
//對行為進行更改
class Visiter1 :public Visitor {
public:
	void visitElementA(ElementA& element) override {
		cout << "Visitor1 process ElementA" << endl;
	}
	void visitElementB(ElementB& element) override {
		cout << "Visitor1 process ElementB" << endl;
	}
};

class Visiter2 :public Visitor {
public:
	void visitElementA(ElementA& element) override {
		cout << "Visitor2 process ElementA" << endl;
	}
	void visitElementB(ElementB& element) override {
		cout << "Visitor2 process ElementB" << endl;
	}
};

int main()
{
	Visiter1 visitor;
	ElementA elementA;
	elementA.accept(visitor);//二次多型辨析

	ElementB elementB;
	elementB.accept(visitor);
	return 0;
}

相關文章