目錄
- 前言
- 問題
- 解決方案
- 結構
- 代碼
前言
中介者是一種行為設計模式,能讓你減少對象之間混亂無序的依賴關系。該模式會限制對象之間的直接交互,迫使它們通過一個中介者對象進行合作。
問題
假如你有一個創建和修改客戶資料的對話框, 它由各種控件組成, 例如 文本框(TextField)、復選框(Checkbox) 和 按鈕(Button)等。
某些表單元素可能會直接進行互動。 例如, 選中“我有一只狗”復選框后可能會顯示一個隱藏文本框用于輸入狗狗的名字。 另一個例子是提交按鈕必須在保存數據前校驗所有輸入內容。
如果直接在表單元素代碼中實現業務邏輯, 你將很難在程序其他表單中復用這些元素類。 例如, 由于復選框類與狗狗的文本框相耦合, 所以將無法在其他表單中使用它。 你要么使用渲染資料表單時用到的所有類,要么一個都不用。
解決方案
中介者模式建議你停止組件之間的直接交流并使其相互獨立。這些組件必須調用特殊的中介者對象, 通過中介者對象重定向調用行為,以間接的方式進行合作。最終,組件僅依賴于一個中介者類,無需與多個其他組件相耦合。
在資料編輯表單的例子中, 對話框(Dialog) 類本身將作為中介者, 其很可能已知自己所有的子元素, 因此你甚至無需在該類中引入新的依賴關系。
絕大部分重要的修改都在實際表單元素中進行。 讓我們想想提交按鈕。之前,當用戶點擊按鈕后,它必須對所有表單元素數值進行校驗。 而現在它的唯一工作是將點擊事件通知給對話框。 收到通知后, 對話框可以自行校驗數值或將任務委派給各元素。 這樣一來, 按鈕不再與多個表單元素相關聯,而僅依賴于對話框類。
你還可以為所有類型的對話框抽取通用接口, 進一步削弱其依賴性。 接口中將聲明一個所有表單元素都能使用的通知方法, 可用于將元素中發生的事件通知給對話框。 這樣一來,所有實現了該接口的對話框都能使用這個提交按鈕了。
采用這種方式, 中介者模式讓你能在單個中介者對象中封裝多個對象間的復雜關系網。 類所擁有的依賴關系越少, 就越易于修改、擴展或復用。
結構
代碼
#include <iostream>
#include <string>
#include <memory>
#include <map>
using namespace std;class AbstractComponent{
public:virtual void operation()=0;virtual ~AbstractComponent(){}
};class AbstractMediator{
public:virtual void notify(const string& sender)=0;virtual void addComponent(const string& name,shared_ptr<AbstractComponent> component)=0;virtual ~AbstractMediator(){}
};
class Dialog:public AbstractMediator{
public:void notify(const string& sender) override {if (sender == "button") {// 當按鈕被觸發時,協調復選框也執行操作cout << "中介者:按鈕被按下,觸發復選框操作" << endl;if (m_component.find("checkbox") != m_component.end()) {m_component["checkbox"]->operation();}} else if (sender == "checkbox") {cout<<"end"<<endl;}}void addComponent(const string& name,shared_ptr<AbstractComponent> component){m_component.insert(make_pair(name,component));}
private:map<string,shared_ptr<AbstractComponent>> m_component;
};class Button:public AbstractComponent{
public:Button(shared_ptr<AbstractMediator> mediator){m=mediator;}void operation() override {cout << "按鈕被按下" << endl;// 自身狀態變化后,通過中介者通知其他組件m->notify("button"); }
private:shared_ptr<AbstractMediator> m;
};
class Checkbox:public AbstractComponent{
public:Checkbox(shared_ptr<AbstractMediator> mediator){m=mediator;}void operation() override{cout << "調用復選框" << endl;// 自身狀態變化后,通過中介者通知其他組件m->notify("checkbox"); }
private:shared_ptr<AbstractMediator> m;
};int main(){auto dialog=make_shared<Dialog>();auto button=make_shared<Button>(dialog);auto checkbox=make_shared<Checkbox>(dialog);dialog->addComponent("button",button);dialog->addComponent("checkbox",checkbox);button->operation();cout<<"----------------"<<endl;checkbox->operation();return 0;
}