前言:
中介者模式是一种行为型设计模式,其核心思想是通过引入一个中介者对象来封装一组对象之间的交互。这种模式可以降低对象之间的耦合度,使得对象之间的交互更加灵活和可维护。
在现实世界中,我们经常会遇到需要协调多个对象之间交互的场景,例如聊天室中的用户之间的消息交互、飞机调度系统中飞机之间的航线调度等。这些场景中,如果对象之间的交互过于复杂,直接的交互方式可能会导致系统难以维护和扩展。而中介者模式的出现正是为了解决这些问题。
通过中介者模式,我们可以将对象之间的交互逻辑集中到中介者对象中,从而降低对象之间的直接依赖关系。这样一来,当系统需要进行修改或扩展时,只需要修改中介者对象而不影响其他对象,使得系统更加灵活和可维护。
总的来说,中介者模式可以帮助我们简化对象之间的交互,降低系统的复杂度,提高系统的可维护性和可扩展性。在实际开发中,合理地运用中介者模式可以使系统更加健壮和灵活。
一、原理及C++示例代码:
中介者模式是一种行为设计模式,它允许对象之间通过一个中介者对象进行通信,而不是直接相互引用。这可以减少对象之间的耦合性,并且使得对象之间的通信更加灵活。
在中介者模式中,中介者对象通常包含了对象之间通信所需的逻辑,并且可以处理对象之间的交互。对象之间的通信通常是通过中介者对象进行的,而不是直接相互引用。
下面是一个简单的C++示例代码,演示了中介者模式的实现:
#include <iostream>
#include <string>
class Mediator;
class Colleague {
public:
virtual void sendMessage(const std::string& message) = 0;
virtual void receiveMessage(const std::string& message) = 0;
virtual void setMediator(Mediator* mediator) = 0;
};
class ConcreteColleague : public Colleague {
public:
void sendMessage(const std::string& message) override {
mediator_->sendMessage(message, this);
}
void receiveMessage(const std::string& message) override {
std::cout << "Received message: " << message << std::endl;
}
void setMediator(Mediator* mediator) override {
mediator_ = mediator;
}
private:
Mediator* mediator_;
};
class Mediator {
public:
void addColleague(Colleague* colleague) {
colleagues_.push_back(colleague);
}
void sendMessage(const std::string& message, Colleague* sender) {
for (auto colleague : colleagues_) {
if (colleague != sender) {
colleague->receiveMessage(message);
}
}
}
private:
std::vector<Colleague*> colleagues_;
};
int main() {
Mediator mediator;
ConcreteColleague colleague1;
ConcreteColleague colleague2;
colleague1.setMediator(&mediator);
colleague2.setMediator(&mediator);
mediator.addColleague(&colleague1);
mediator.addColleague(&colleague2);
colleague1.sendMessage("Hello, colleague2!");
colleague2.sendMessage("Hi, colleague1!");
return 0;
}
在上面的示例中,Colleague 是同事类的抽象基类,ConcreteColleague 是具体的同事类,Mediator 是中介者类。同事类通过中介者对象进行通信,而不是直接相互引用。这样可以减少对象之间的耦合性,并且使得对象之间的通信更加灵活。
二、结构图
中介者模式的结构图包括以下几个要素:
-
Mediator(中介者):中介者是一个接口或抽象类,它定义了同事对象之间通信的方法。
-
ConcreteMediator(具体中介者):具体中介者是中介者的实现类,它包含了同事对象之间通信的具体逻辑。
-
Colleague(同事):同事是指需要进行通信的对象,它们通过中介者进行通信而不是直接相互引用。
-
ConcreteColleague(具体同事):具体同事是同事的实现类,它实现了同事接口,并且包含了需要与其他同事对象进行通信的具体逻辑。
下面是中介者模式的结构图示例:
+-----------------+ +-----------------+
| Colleague | | Colleague |
+-----------------+ +-----------------+
/|\ /|\
| |
| |
| |
+---------------------+ +---------------------+
| ConcreteColleague | | ConcreteColleague |
+---------------------+ +---------------------+
| |
| |
| |
+-----------------+ +-----------------+
| Mediator | | Mediator |
+-----------------+ +-----------------+
/|\ /|\
| |
| |
| |
+-----------------+ +-----------------+
| ConcreteMediator| | ConcreteMediator|
+-----------------+ +-----------------+
在上面的结构图中,Colleague 表示同事的接口或抽象类,ConcreteColleague 表示具体的同事类;Mediator 表示中介者的接口或抽象类,ConcreteMediator 表示具体的中介者类。同事对象通过中介者对象进行通信,而不是直接相互引用,这样可以减少对象之间的耦合性。
三、使用场景
中介者模式通常适用于以下场景:
-
当一个系统中对象之间的交互比较复杂,导致对象之间的耦合度较高时,可以考虑使用中介者模式来简化对象之间的通信。
-
当一个对象需要与多个其他对象进行通信,但是直接与这些对象进行交互会导致系统过于复杂时,可以使用中介者模式来集中管理对象之间的通信。
-
当对象之间的交互需要进行扩展和修改时,中介者模式可以使得修改和扩展更加灵活,因为所有的通信逻辑都集中在中介者中。
-
当对象之间的通信导致循环依赖或者大量的逻辑交织在一起时,可以使用中介者模式来简化对象之间的关系,减少耦合度。
-
在图形界面应用程序中,中介者模式常常用于管理界面元素之间的交互,例如按钮、文本框、下拉框等组件之间的通信。
总之,中介者模式适用于需要简化对象之间通信关系、降低耦合度、集中管理对象交互逻辑的情况。
具体场景代码:
假设有一个简单的聊天室程序,其中多个用户(Colleague)可以通过中介者(Mediator)进行消息的发送和接收。
#include <iostream>
#include <string>
#include <vector>
class Mediator;
// 抽象同事类
class Colleague {
public:
virtual void sendMessage(const std::string& message) = 0;
virtual void receiveMessage(const std::string& message) = 0;
virtual void setMediator(Mediator* mediator) = 0;
};
// 具体同事类
class ConcreteColleague : public Colleague {
public:
ConcreteColleague(const std::string& name) : name(name), mediator(nullptr) {}
void sendMessage(const std::string& message) override {
mediator->sendMessage(this, message);
}
void receiveMessage(const std::string& message) override {
std::cout << name << " received: " << message << std::endl;
}
void setMediator(Mediator* mediator) override {
this->mediator = mediator;
}
private:
std::string name;
Mediator* mediator;
};
// 抽象中介者类
class Mediator {
public:
virtual void sendMessage(Colleague* colleague, const std::string& message) = 0;
virtual void addColleague(Colleague* colleague) = 0;
};
// 具体中介者类
class ConcreteMediator : public Mediator {
public:
void sendMessage(Colleague* colleague, const std::string& message) override {
for (auto c : colleagues) {
if (c != colleague) {
c->receiveMessage(message);
}
}
}
void addColleague(Colleague* colleague) override {
colleagues.push_back(colleague);
}
private:
std::vector<Colleague*> colleagues;
};
int main() {
ConcreteMediator mediator;
ConcreteColleague colleague1("Alice");
ConcreteColleague colleague2("Bob");
colleague1.setMediator(&mediator);
colleague2.setMediator(&mediator);
mediator.addColleague(&colleague1);
mediator.addColleague(&colleague2);
colleague1.sendMessage("Hello, Bob!");
colleague2.sendMessage("Hi, Alice!");
return 0;
}
在上面的示例中,ConcreteColleague 表示具体的同事类,ConcreteMediator 表示具体的中介者类。同事对象通过中介者对象进行通信,而不是直接相互引用。在 main 函数中,创建了一个中介者对象和两个同事对象,然后通过中介者对象进行消息的发送和接收。
假设有一个简单的飞机交通管制系统,多架飞机(Colleague)需要通过中介者(Mediator)进行通信和协调飞行。
#include <iostream>
#include <string>
#include <vector>
class Mediator;
// 抽象飞机类
class Aircraft {
public:
virtual void requestTakeoff() = 0;
virtual void receivePermission() = 0;
virtual void setMediator(Mediator* mediator) = 0;
};
// 具体飞机类
class ConcreteAircraft : public Aircraft {
public:
ConcreteAircraft(const std::string& name) : name(name), mediator(nullptr) {}
void requestTakeoff() override {
mediator->requestTakeoff(this);
}
void receivePermission() override {
std::cout << name << " has received permission to take off." << std::endl;
}
void setMediator(Mediator* mediator) override {
this->mediator = mediator;
}
private:
std::string name;
Mediator* mediator;
};
// 抽象中介者类
class Mediator {
public:
virtual void requestTakeoff(Aircraft* aircraft) = 0;
virtual void grantPermission() = 0;
};
// 具体中介者类
class AirTrafficControl : public Mediator {
public:
void requestTakeoff(Aircraft* aircraft) override {
pendingAircraft.push_back(aircraft);
grantPermission();
}
void grantPermission() override {
if (!pendingAircraft.empty()) {
pendingAircraft.front()->receivePermission();
pendingAircraft.erase(pendingAircraft.begin());
}
}
private:
std::vector<Aircraft*> pendingAircraft;
};
int main() {
AirTrafficControl mediator;
ConcreteAircraft aircraft1("Flight 001");
ConcreteAircraft aircraft2("Flight 002");
aircraft1.setMediator(&mediator);
aircraft2.setMediator(&mediator);
aircraft1.requestTakeoff();
aircraft2.requestTakeoff();
return 0;
}
在上面的示例中,ConcreteAircraft 表示具体的飞机类,AirTrafficControl 表示具体的中介者类。飞机对象通过中介者对象进行请求起飞,中介者会进行协调并向飞机发放起飞许可。在 main 函数中,创建了一个中介者对象和两个飞机对象,然后通过中介者对象进行起飞请求和许可的处理。
四、优缺点
中介者模式的优点包括:
- 减少了对象之间的直接通信,将复杂的交互逻辑集中在中介者中,降低了对象之间的耦合度,使得系统更易于维护和扩展。
- 可以简化对象之间的交互,因为对象无需了解其他对象的详细信息,只需要与中介者进行通信即可。
- 提高了系统的可复用性和灵活性,因为中介者模式将交互逻辑集中在一个地方,当需要修改或扩展交互逻辑时,只需修改中介者而无需修改各个同事类。
中介者模式的缺点包括:
- 中介者可能会变得过于复杂,因为所有的交互逻辑都集中在中介者中,可能会导致中介者变得庞大和难以维护。
- 中介者模式可能会导致性能问题,因为所有的通信都需要经过中介者进行处理,可能会增加系统的负担。
在设计中介者模式时,需要权衡对象之间的交互复杂性和中介者的复杂性,以及对性能的影响,从而选择合适的设计方案。
五、常见的10个面试题:
当面试官提出关于中介者模式的问题时,你可能会遇到以下一些常见的问题,以及相应的答案解析:
-
问题:什么是中介者模式? 答案解析:中介者模式是一种行为型设计模式,它通过引入一个中介者对象来封装一组对象之间的交互,从而降低对象之间的耦合度,使得对象之间的交互更加灵活和可维护。
-
问题:中介者模式的结构包括哪些角色? 答案解析:中介者模式包括中介者(Mediator)、具体中介者(ConcreteMediator)、同事(Colleague)和具体同事(ConcreteColleague)等角色。
-
问题:中介者模式的优点有哪些? 答案解析:中介者模式的优点包括降低对象之间的耦合度、简化对象之间的交互、提高系统的可维护性和可扩展性等。
-
问题:中介者模式的缺点有哪些? 答案解析:中介者模式可能会导致中介者对象过于复杂、性能问题等。
-
问题:中介者模式和观察者模式有何区别? 答案解析:中介者模式和观察者模式都是用于对象之间的通信,但中介者模式是通过中介者对象来进行通信,而观察者模式是通过观察者和被观察者之间的订阅-发布机制来进行通信。
-
问题:中介者模式在实际项目中的应用场景有哪些? 答案解析:中介者模式适用于系统中对象之间的交互较为复杂的场景,例如聊天室、飞机调度系统等。
-
问题:中介者模式和代理模式有何区别? 答案解析:中介者模式是用于对象之间的通信,而代理模式是用于控制对对象的访问。
-
问题:中介者模式和策略模式有何区别? 答案解析:中介者模式是用于对象之间的通信,而策略模式是用于封装可互换的算法。
-
问题:中介者模式如何解决对象之间的循环依赖问题? 答案解析:中介者模式通过引入中介者对象来解耦对象之间的直接依赖关系,从而避免循环依赖的问题。
-
问题:在中介者模式中,同事对象如何与中介者进行通信? 答案解析:同事对象通过中介者提供的接口来发送消息,中介者将消息传递给其他同事对象,从而实现对象之间的通信。