介绍
中介者模式用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为模式。
实现
myclass.h
cpp
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
class Mediator;
class Colleague { // 抽象同事类
public:
Colleague(Mediator *mMediator);
virtual void method1() = 0; // 处理自己的行为
virtual void method2() = 0; // 与中介者进行通讯
protected:
Mediator *m_mediator;
};
class Mediator { // 抽象中介者;
public:
void registerColleague(Colleague *colleague);
virtual void operation(Colleague *colleague) = 0;
protected:
std::vector<Colleague *> m_colleagues;
};
class ConcreteMediator : public Mediator { // 具体中介者
public:
void operation(Colleague *colleague) override;
};
class ConcreteColleagueA : public Colleague { // 具体同事类A
public:
ConcreteColleagueA(Mediator *mediator);
void method1() override;
void method2() override;
};
class ConcreteColleagueB : public Colleague { // 具体同事类B
public:
ConcreteColleagueB(Mediator *mediator);
void method1() override;
void method2() override;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp
cpp
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>
Colleague::Colleague(Mediator *mMediator) : m_mediator(mMediator) {
}
void Mediator::registerColleague(Colleague *colleague) {
if (colleague) {
m_colleagues.push_back(colleague);
}
}
void ConcreteMediator::operation(Colleague *colleague) {
for (auto &c : m_colleagues) {
if (c != colleague) {
c->method1();
}
}
}
ConcreteColleagueA::ConcreteColleagueA(Mediator *mediator) : Colleague(mediator){
}
void ConcreteColleagueA::method1() {
std::cout << "ConcreteColleagueA处理自身逻辑" << std::endl;
}
void ConcreteColleagueA::method2() {
std::cout << "ConcreteColleagueA通知中介者" << std::endl;
if (m_mediator) {
m_mediator->operation(this);
}
}
ConcreteColleagueB::ConcreteColleagueB(Mediator *mediator) : Colleague(mediator){
}
void ConcreteColleagueB::method1() {
std::cout << "ConcreteColleagueB处理自身逻辑" << std::endl;
}
void ConcreteColleagueB::method2() {
std::cout << "ConcreteColleagueB通知中介者" << std::endl;
if (m_mediator) {
m_mediator->operation(this);
}
}
main.cpp
cpp
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Mediator *mediator = new ConcreteMediator();
Colleague *colleagueA = new ConcreteColleagueA(mediator);
Colleague *colleagueB = new ConcreteColleagueB(mediator);
mediator->registerColleague(colleagueA);
mediator->registerColleague(colleagueB);
colleagueA->method2();
colleagueB->method2();
delete colleagueA;
delete colleagueB;
delete mediator;
return 0;
}
总结
优点
-
中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互。一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星形结构。
-
中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,可以独立地改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合开闭原则。
-
可以减少大量同事子类生成。中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需要生成新的中介者子类即可,这使得各个同事类可以被重用,无须对同事类进行扩展。
缺点
- 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
适用场景
-
系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
-
一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
-
想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。
练习
myclass.h
cpp
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
class Mediator;
class Pane { // 抽象同事类
public:
Pane(const std::string &name, Mediator *mediator);
virtual void update() = 0; // 处理自己的行为
virtual void tellOther() = 0; // 与中介者进行通讯
protected:
Mediator *m_mediator;
std::string m_name;
};
class Mediator { // 抽象中介者;
public:
void registerPane(Pane *pane);
virtual void operation(Pane *pane) = 0;
protected:
std::vector<Pane *> m_panes;
};
class Window : public Mediator { // 具体中介者
public:
void operation(Pane *pane) override;
};
class TextPane : public Pane { // 具体同事类TextPane
public:
TextPane(const std::string &name, Mediator *mediator);
void update() override;
void tellOther() override;
};
class ListPane : public Pane { // 具体同事类ListPane
public:
ListPane(const std::string &name, Mediator *mediator);
void update() override;
void tellOther() override;
};
class GraphicPane : public Pane { // 具体同事类GraphicPane
public:
GraphicPane(const std::string &name, Mediator *mediator);
void update() override;
void tellOther() override;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp
cpp
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>
Pane::Pane(const std::string &name, Mediator *mediator) : m_name(name), m_mediator(mediator) {
}
void Mediator::registerPane(Pane *pane) {
if (pane) {
m_panes.push_back(pane);
}
}
void Window::operation(Pane *pane) {
for (auto &c : m_panes) {
if (c != pane) {
c->update();
}
}
}
TextPane::TextPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){
}
void TextPane::update() {
std::cout << m_name << "更新显示" << std::endl;
}
void TextPane::tellOther() {
std::cout << m_name << "通知Window" << std::endl;
if (m_mediator) {
m_mediator->operation(this);
}
}
ListPane::ListPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){
}
void ListPane::update() {
std::cout << m_name << "更新显示" << std::endl;
}
void ListPane::tellOther() {
std::cout << m_name << "通知Window" << std::endl;
if (m_mediator) {
m_mediator->operation(this);
}
}
GraphicPane::GraphicPane(const std::string &name, Mediator *mediator) : Pane(name, mediator){
}
void GraphicPane::update() {
std::cout << m_name << "更新显示" << std::endl;
}
void GraphicPane::tellOther() {
std::cout << m_name << "通知Window" << std::endl;
if (m_mediator) {
m_mediator->operation(this);
}
}
main.cpp
cpp
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Mediator *mediator = new Window();
Pane *text = new TextPane("text", mediator);
Pane *list = new ListPane("list", mediator);
Pane *graphic = new ListPane("graphic", mediator);
mediator->registerPane(text);
mediator->registerPane(list);
mediator->registerPane(graphic);
std::cout << "-------------------------" << std::endl;
text->tellOther();
std::cout << "-------------------------" << std::endl;
list->tellOther();
std::cout << "-------------------------" << std::endl;
graphic->tellOther();
std::cout << "-------------------------" << std::endl;
delete text;
delete list;
delete graphic;
delete mediator;
return 0;
}