设计模式 20 中介者模式 Mediator Pattern
1.定义
中介者模式(Mediator Pattern)是一种行为型设计模式,它通过封装对象之间的交互,促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象,将系统中对象之间复杂的交互关系集中管理,使得对象之间不直接相互通信,而是通过中介者进行通信,从而降低对象之间的耦合度,提高系统的可维护性和扩展性。
在中介者模式中,中介者对象充当了协调者的角色,负责处理系统中各个相互关联对象之间的交互,对于系统其他对象来说,与中介者进行通信是唯一的接口。此外,中介者模式还可以实现集中化控制,将系统变得更加灵活,并且可以更方便地修改系统的行为。
2.内涵
中介者模式(Mediator Pattern)主要角色:
- 中介者(Mediator):定义一个接口用于与各同事对象之间的通信,可以是抽象类或接口,并且通常包含一个或多个方法用于处理不同对象之间的交互。
- 具体中介者(Concrete Mediator):实现中介者接口,负责协调各个同事对象的交互关系。
- 同事(Colleague):每个同事对象都有一个中介者对象的引用,通过中介者来与其他同事对象进行通信。
- 具体同事(Concrete Colleague):实现同事接口的类,与其他同事对象进行交互,通过中介者来处理与其他同事对象的通信。
中介者模式通常适用的场景:
系统中的对象之间具有复杂的交互关系,需要通过中介者来协调。
系统需要支持松耦合的设计,希望减少对象之间的直接依赖。
多个对象之间存在循环依赖,通过引入中介者来解决循环依赖问题。
上述角色之间的关系,简而言之,绘制如下UML 。
3.使用示例
#include <iostream>
#include <string>
/**
* The Mediator interface declares a method used by components to notify the
* mediator about various events. The Mediator may react to these events and
* pass the execution to other components.
*/
class BaseComponent;
class Mediator {
public:
virtual void Notify(BaseComponent *sender, std::string event) const = 0;
};
/**
* The Base Component provides the basic functionality of storing a mediator's
* instance inside component objects.
*/
class BaseComponent {
protected:
Mediator *mediator_;
public:
BaseComponent(Mediator *mediator = nullptr) : mediator_(mediator) {
}
void set_mediator(Mediator *mediator) {
this->mediator_ = mediator;
}
};
/**
* Concrete Components implement various functionality. They don't depend on
* other components. They also don't depend on any concrete mediator classes.
*/
class Component1 : public BaseComponent {
public:
void DoA() {
std::cout << "Component 1 does A.\n";
this->mediator_->Notify(this, "A");
}
void DoB() {
std::cout << "Component 1 does B.\n";
this->mediator_->Notify(this, "B");
}
};
class Component2 : public BaseComponent {
public:
void DoC() {
std::cout << "Component 2 does C.\n";
this->mediator_->Notify(this, "C");
}
void DoD() {
std::cout << "Component 2 does D.\n";
this->mediator_->Notify(this, "D");
}
};
/**
* Concrete Mediators implement cooperative behavior by coordinating several
* components.
*/
class ConcreteMediator : public Mediator {
private:
Component1 *component1_;
Component2 *component2_;
public:
ConcreteMediator(Component1 *c1, Component2 *c2) : component1_(c1), component2_(c2) {
this->component1_->set_mediator(this);
this->component2_->set_mediator(this);
}
void Notify(BaseComponent *sender, std::string event) const override {
if (event == "A") {
std::cout << "Mediator reacts on A and triggers following operations:\n";
this->component2_->DoC();
}
if (event == "D") {
std::cout << "Mediator reacts on D and triggers following operations:\n";
this->component1_->DoB();
this->component2_->DoC();
}
}
};
/**
* The client code.
*/
void ClientCode() {
Component1 *c1 = new Component1;
Component2 *c2 = new Component2;
ConcreteMediator *mediator = new ConcreteMediator(c1, c2);
std::cout << "Client triggers operation A.\n";
c1->DoA();
std::cout << "\n";
std::cout << "Client triggers operation D.\n";
c2->DoD();
delete c1;
delete c2;
delete mediator;
}
int main() {
ClientCode();
return 0;
}
类图如下所示
4.注意事项
在使用中介者模式(Mediator Pattern)时,需要注意以下几个点和可能遇到的坑:
- 考虑中介者对象的复杂性:中介者对象负责管理对象之间的交互关系,可能会变得复杂,特别是在系统中有大量对象需要协作时。因此,在设计中介者对象时,需要仔细考虑其职责和功能,避免过于臃肿和复杂。
- 避免中介者成为系统瓶颈:由于所有对象之间的通信通过中介者进行,中介者可能会成为系统的性能瓶颈。因此,在使用中介者模式时,需要考虑中介者的设计和实现是否能够满足系统的性能需求。
- 避免过度集中化控制:中介者模式的目的是降低对象之间的耦合度并集中控制交互逻辑,但过度集中化控制可能导致系统设计变得僵化和不灵活。因此,在设计中介者模式时,需要根据实际需求来平衡对象之间的关系和控制逻辑。
- 同事对象之间的交互:中介者模式可以减少对象之间的直接依赖,但所有对象间的交互都需要通过中介者进行,可能会导致系统的复杂性增加。因此,需要合理划分对象的职责和功能,避免同事对象之间过于紧密的交互。
- 考虑扩展性和灵活性:中介者模式可以使系统更加灵活和可扩展,但在设计中介者对象时,需要考虑系统的未来发展和变化。确保中介者模式能够支持系统的扩展和变化,避免设计过于局限于当前需求。
5.最佳实践
在设计中介者模式(Mediator Pattern)时,以确保模式的有效实现和系统的可维护性。以下一些可以参考的设计实践:
- 使用抽象中介者(Mediator)接口:定义一个抽象中介者接口,定义同事对象与中介者之间的通信方法,以实现解耦和系统扩展。
- 采用单一职责原则:确保中介者对象的职责单一,不要让中介者对象负责过多的功能和逻辑,以提高系统的灵活性和可维护性。
- 考虑中介者对象的实现方式:中介者对象可以采用抽象类或接口的形式实现,也可以选择使用具体类实现。根据实际需求和系统复杂度选择适合的实现方式。
- 考虑同事对象的接口设计:同事对象之间通过中介者进行通信,因此需要定义好同事对象的接口,确保适当的信息传递和约束。
- 考虑系统的扩展性:在设计中介者模式时,要考虑系统未来的扩展和变化,确保模式能够支持新的同事对象和中介者对象的加入,以确保系统的可扩展性。
- 想清楚对象之间的通信流程:在设计中介者模式时,要精确定义对象之间的通信流程和交互规则,避免对象间的混乱和冲突。
- 使用工厂模式创建中介者和同事对象:可以使用工厂模式来创建中介者对象和同事对象,以确保对象的创建过程更加灵活和可控。
- 使用观察者模式实现通知机制:可以结合观察者模式实现中介者对象向同事对象发送通知的机制,以实现更加灵活的通信方式。
6.总结
中介者模式也存在缺点,如中介者对象的复杂性可能会随着系统的复杂性增加而增加,同时中介者对象可能会成为系统中的瓶颈。