中介者模式
简介
参考链接
中介者模式是一种行为设计模式,当一个项目中模块比较多的时候,如果模块之间交互很多,很复杂的时候,可以考虑用中介者模式,每个模块都通过中介者进行交互,各个模块之间不会有耦合。实现了一种类与类之间的交互方式。
MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。
UML类图
代码示例
#include <iostream>
class Mediator;
class IUser;
class IMediator {
public:
virtual void set_user1(IUser *user) = 0;
virtual void set_user2(IUser *user) = 0;
virtual void transmit(const std::string &msg, IUser *user) = 0;
};
class IUser {
public:
IUser(IMediator *m): mediator(m) {}
void send(const std::string &msg) {
mediator->transmit(msg, this);
}
virtual void recv(const std::string &msg) = 0;
IMediator *mediator = nullptr;
};
class User1: public IUser {
public:
User1(IMediator *m): IUser(m) {}
virtual void recv(const std::string &msg) {
std::cout << "User1 recv msg: " << msg << std::endl;
}
};
class User2: public IUser {
public:
User2(IMediator *m): IUser(m) {}
virtual void recv(const std::string &msg) {
std::cout << "User2 recv msg: " << msg << std::endl;
}
};
class Mediator: public IMediator {
public:
virtual void set_user1(IUser *user) {
user1 = user;
}
virtual void set_user2(IUser *user) {
user2 = user;
}
virtual void transmit(const std::string &msg, IUser *user) {
if (user == user1) {
user2->recv(msg);
} else if(user == user2) {
user1->recv(msg);
}
}
IUser *user1 = nullptr;
IUser *user2 = nullptr;
};
int main() {
IMediator *mediator = new Mediator();
IUser *user1 = new User1(mediator);
IUser *user2 = new User2(mediator);
mediator->set_user1(user1);
mediator->set_user2(user2);
user1->send("Hello");
user2->send("Hello");
user1->send("Hello");
user1->send("Hello");
delete user1;
delete user2;
delete mediator;
}
/*
run result:
User2 recv msg: Hello
User1 recv msg: Hello
User2 recv msg: Hello
User2 recv msg: Hello
*/
例子二
#include <iostream>
class Mediator;
class IUser;
// 中介者接口类
class IMediator {
public:
virtual void transmit(const std::string &msg, IUser *user) = 0;
};
// 模块user抽象类
class IUser {
public:
IUser() {}
void send(const std::string &msg) {
mediator_->transmit(msg, this);
}
virtual void set_mediator(IMediator *mediator) {
mediator_ = mediator;
}
virtual void recv(const std::string &msg) = 0;
IMediator *mediator_ = nullptr;
};
// 具体user1
class User1: public IUser {
public:
User1() {}
virtual void recv(const std::string &msg) {
std::cout << "User1 recv msg: " << msg << std::endl;
}
};
// 具体user2
class User2: public IUser {
public:
User2() {}
virtual void recv(const std::string &msg) {
std::cout << "User2 recv msg: " << msg << std::endl;
}
};
// 具体中介者类
class Mediator: public IMediator {
public:
Mediator(IUser *user1, IUser *user2): user1_(user1), user2_(user2) {
user1_->set_mediator(this);
user2_->set_mediator(this);
}
// transmit 实现每个模块的交互
// user1->send==>user2->revv
// user2->send==>user1->revv
virtual void transmit(const std::string &msg, IUser *user) {
if (user == user1_) {
user2_->recv(msg);
} else if(user == user2_) {
user1_->recv(msg);
}
}
IUser *user1_ = nullptr;
IUser *user2_ = nullptr;
};
int main() {
IUser *user1 = new User1();
IUser *user2 = new User2();
IMediator *mediator = new Mediator(user1, user2);
user1->send("Hello");
user2->send("Hello");
user1->send("Hello");
user1->send("Hello");
delete user1;
delete user2;
delete mediator;
}
/*
run result:
User2 recv msg: Hello
User1 recv msg: Hello
User2 recv msg: Hello
User2 recv msg: Hello
*/
例子三
#include <iostream>
#include <vector>
#include <string>
class Mediator;
class IUser;
struct commu_node{
IUser *from;
IUser *to;
};
class IMediator {
public:
virtual void init(std::vector<IUser *> &user_vec,
std::vector<commu_node> &node_vec) = 0;
virtual void transmit(IUser *self, char *data, size_t size) = 0;
};
class IUser {
public:
IUser(const std::string &name): name_(name) {}
void send(char *data, size_t size) {
mediator_->transmit(this, data, size);
}
virtual void set_mediator(IMediator *mediator) {
mediator_ = mediator;
}
virtual void recv(char *data, size_t size) = 0;
IMediator *mediator_ = nullptr;
std::string name_;
};
class User1: public IUser {
public:
User1(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
std::cout << name_ << " recv msg: " << data << std::endl;
}
};
class User2: public IUser {
public:
User2(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
std::cout << name_ << " recv msg: " << data << std::endl;
}
};
class Mediator: public IMediator {
public:
Mediator() { }
virtual void init(std::vector<IUser *> &user_vec,
std::vector<commu_node> &node_vec) {
for (int i = 0; i < user_vec.size(); i++) {
user_vec[i]->set_mediator(this);
}
// add check
// ......
node_vec_ = node_vec;
}
virtual void transmit(IUser *self, char *data, size_t size) {
int i = 0;
for (i = 0; i < node_vec_.size(); i++) {
if (self == node_vec_[i].from) {
std::cout << "[" << self->name_<< "]->[" << node_vec_[i].to->name_<< "]"
<< " is: " << data << std::endl;
node_vec_[i].to->recv(data, size);
break;
}
}
if (i == node_vec_.size()) {
std::cout << "transmit failed: " << self->name_ << "->unknow" << std::endl;
}
}
std::vector<commu_node> node_vec_;
};
int main() {
IUser *user1 = new User1("user1");
IUser *user2 = new User2("user2");
std::vector<IUser *> user_vec{user1, user2};
std::vector<commu_node> node_vec{{user1, user2}, {user2, user1}};
IMediator *mediator = new Mediator();
mediator->init(user_vec, node_vec);
char data_tmp1[10] = "hello";
char data_tmp2[10] = "I am fine";
user1->send(data_tmp1, 10);
std::cout << "-------------" << std::endl;
user2->send(data_tmp2, 10);
user1->send(data_tmp1, 10);
user1->send(data_tmp1, 10);
delete user1;
delete user2;
delete mediator;
}
/*
run result:
[user1]->[user2] is: hello
user2 recv msg: hello
-------------
[user2]->[user1] is: I am fine
user1 recv msg: I am fine
[user1]->[user2] is: hello
user2 recv msg: hello
[user1]->[user2] is: hello
user2 recv msg: hello
*/
例子四
#include <iostream>
#include <vector>
#include <string>
class Mediator;
class IUser;
struct commu_node{
IUser *from_ = nullptr;
IUser *to_ = nullptr;
void to(IUser *to_tmp) {
to_ = to_tmp;
}
};
class IMediator {
public:
virtual void init(std::vector<IUser *> &user_vec) = 0;
virtual void transmit(IUser *self, char *data, size_t size) = 0;
virtual commu_node *from(IUser *from_tmp) = 0;
};
class IUser {
public:
IUser(const std::string &name): name_(name) {}
void send(char *data, size_t size) {
mediator_->transmit(this, data, size);
}
virtual void set_mediator(IMediator *mediator) {
mediator_ = mediator;
}
virtual void recv(char *data, size_t size) = 0;
IMediator *mediator_ = nullptr;
std::string name_;
};
class User1: public IUser {
public:
User1(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
std::cout << name_ << " recv msg: " << data << std::endl;
}
};
class User2: public IUser {
public:
User2(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
std::cout << name_ << " recv msg: " << data << std::endl;
}
};
class Mediator: public IMediator {
public:
Mediator() { }
virtual void init(std::vector<IUser *> &user_vec) {
for (int i = 0; i < user_vec.size(); i++) {
user_vec[i]->set_mediator(this);
}
}
virtual void transmit(IUser *self, char *data, size_t size) {
int i = 0;
for (i = 0; i < node_vec_.size(); i++) {
if (self == node_vec_[i].from_) {
std::cout << "[" << self->name_<< "]->[" << node_vec_[i].to_->name_<< "]"
<< " is: " << data << std::endl;
node_vec_[i].to_->recv(data, size);
break;
}
}
if (i == node_vec_.size()) {
std::cout << "transmit failed: " << self->name_ << "->unknow" << std::endl;
}
}
virtual commu_node *from(IUser *from_tmp) {
commu_node node_tmp;
node_tmp.from_ = from_tmp;
node_vec_.push_back(node_tmp);
return &node_vec_[node_vec_.size() - 1];
}
std::vector<commu_node> node_vec_;
};
int main() {
IUser *user1 = new User1("user1");
IUser *user2 = new User2("user2");
std::vector<IUser *> user_vec{user1, user2};
IMediator *mediator = new Mediator();
mediator->init(user_vec);
mediator->from(user1)->to(user2);
mediator->from(user2)->to(user1);
char data_tmp1[10] = "hello";
char data_tmp2[10] = "I am fine";
user1->send(data_tmp1, 10);
std::cout << "-------------" << std::endl;
user2->send(data_tmp2, 10);
std::cout << "-------------" << std::endl;
delete user1;
delete user2;
delete mediator;
}
/*
[user1]->[user2] is: hello
user2 recv msg: hello
-------------
[user2]->[user1] is: I am fine
user1 recv msg: I am fine
-------------
*/
例子五
#include <iostream>
#include <vector>
#include <string>
class Mediator;
class IUser;
struct commu_node{
IUser *from_ = nullptr;
IUser *to_ = nullptr;
void to(IUser *to_tmp) {
to_ = to_tmp;
}
};
class IMediator {
public:
virtual void init(std::vector<IUser *> &user_vec) = 0;
virtual void get_send_list(IUser *self, std::vector<IUser *> &to_list) = 0;
virtual void send_msg(std::vector<IUser *> &to_list, char *data, size_t size) = 0;
virtual commu_node *from(IUser *from_tmp) = 0;
};
class IUser {
public:
IUser(const std::string &name): name_(name) {}
virtual void set_mediator(IMediator *mediator) {
mediator_ = mediator;
}
virtual void send(char *data, size_t size) {
std::vector<IUser *> to_list;
mediator_->get_send_list(this, to_list);
if (to_list.size() == 0) {
return;
}
// debug
std::cout << "[" << name_<< "] send <" << data << "> to:";
for (int i = 0; i < to_list.size(); i++) {
std::cout << " [" << to_list[i]->name_ << "]";
}
std::cout << std::endl;
mediator_->send_msg(to_list, data, size);
}
virtual void recv(char *data, size_t size) = 0;
IMediator *mediator_ = nullptr;
std::string name_;
};
class User1: public IUser {
public:
User1(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
// std::cout << name_ << " recv msg: " << data << std::endl;
send(data, size);
}
};
class User2: public IUser {
public:
User2(const std::string &name): IUser(name) {}
virtual void recv(char *data, size_t size) {
// std::cout << name_ << " recv msg: " << data << std::endl;
send(data, size);
}
};
class Mediator: public IMediator {
public:
Mediator() { }
virtual void init(std::vector<IUser *> &user_vec) {
for (int i = 0; i < user_vec.size(); i++) {
user_vec[i]->set_mediator(this);
}
}
virtual void get_send_list(IUser *self, std::vector<IUser *> &to_list) {
for (int i = 0; i < node_vec_.size(); i++) {
if (self == node_vec_[i].from_) {
to_list.push_back(node_vec_[i].to_);
}
}
}
virtual void send_msg(std::vector<IUser *> &to_list, char *data, size_t size) {
for (int i = 0; i < to_list.size(); i++) {
to_list[i]->recv(data, size);
}
}
virtual commu_node *from(IUser *from_tmp) {
commu_node node_tmp;
node_tmp.from_ = from_tmp;
node_vec_.push_back(node_tmp);
return &node_vec_[node_vec_.size() - 1];
}
std::vector<commu_node> node_vec_;
};
int main() {
IUser *user1 = new User1("user1");
IUser *user2 = new User1("user2");
IUser *user3 = new User1("user3");
IUser *user4 = new User1("user4");
IUser *user5 = new User1("user5");
std::vector<IUser *> user_vec{user1, user2, user3, user4, user5};
IMediator *mediator = new Mediator();
mediator->init(user_vec);
mediator->from(user1)->to(user2);
// mediator->from(user1)->to(user2);
mediator->from(user2)->to(user3);
mediator->from(user3)->to(user4);
mediator->from(user4)->to(user5);
char data_tmp1[10] = "hello";
user1->send(data_tmp1, 10);
std::cout << "-------------" << std::endl;
delete user1;
delete user2;
delete user3;
delete user4;
delete user5;
delete mediator;
}
/*
./a.out
[user1] send <hello> to: [user2]
[user2] send <hello> to: [user3]
[user3] send <hello> to: [user4]
[user4] send <hello> to: [user5]
*/
例子六
#include <iostream>
#include <vector>
#include <string>
#include <memory>
class Mediator;
class IUser;
using spIuser = std::shared_ptr<IUser>;
class Message {
public:
std::vector<char> vec_char;
};
struct commu_node{
spIuser from_ = nullptr;
spIuser to_ = nullptr;
void to(spIuser to_tmp) {
to_ = to_tmp;
}
};
class IMediator {
public:
virtual ~IMediator() {};
// virtual void init(std::vector<spIuser> &user_vec) = 0;
virtual void get_send_list(IUser *self, std::vector<spIuser> &to_list) = 0;
virtual void send_msg(std::vector<spIuser> &to_list,
std::shared_ptr<Message> msg) = 0;
virtual std::shared_ptr<commu_node> &from(spIuser from_tmp) = 0;
};
class IUser {
public:
IUser(const std::string &name): name_(name) {}
virtual ~IUser() {}
virtual void set_mediator(IMediator *mediator) {
mediator_ = mediator;
}
virtual void send(std::shared_ptr<Message> msg) {
std::vector<spIuser> to_list;
mediator_->get_send_list(this, to_list);
if (to_list.size() == 0) {
return;
}
// debug
std::cout << "[" << name_<< "] send <" << msg->vec_char[0] << "> to:";
for (int i = 0; i < to_list.size(); i++) {
std::cout << " [" << to_list[i]->name_ << "]";
}
std::cout << std::endl;
mediator_->send_msg(to_list, msg);
}
virtual void recv(std::shared_ptr<Message> msg) = 0;
IMediator *mediator_ = nullptr;
std::string name_;
};
class User1: public IUser {
public:
User1(const std::string &name): IUser(name) {}
virtual ~User1() {}
virtual void recv(std::shared_ptr<Message> msg) {
send(msg);
}
};
// class User2: public IUser {
// public:
// User2(const std::string &name): IUser(name) {}
// virtual void recv(std::shared_ptr<Message> msg) {
// // std::cout << name_ << " recv msg: " << data << std::endl;
// msg.vec_char[0] = 'A';
// send(msg);
// }
// };
class Mediator: public IMediator {
public:
Mediator(std::vector<spIuser> &user_vec) {
for (int i = 0; i < user_vec.size(); i++) {
user_vec[i]->set_mediator(this);
}
}
virtual ~Mediator() {}
// virtual void init(std::vector<spIuser> &user_vec) {
// for (int i = 0; i < user_vec.size(); i++) {
// user_vec[i]->set_mediator(this);
// }
// }
virtual void get_send_list(IUser *self, std::vector<spIuser> &to_list) {
for (int i = 0; i < node_vec_.size(); i++) {
if (self == node_vec_[i]->from_.get()) {
to_list.push_back(node_vec_[i]->to_);
}
}
}
virtual void send_msg(std::vector<spIuser> &to_list,
std::shared_ptr<Message> msg) {
for (int i = 0; i < to_list.size(); i++) {
to_list[i]->recv(msg);
}
}
virtual std::shared_ptr<commu_node> &from(spIuser from_tmp) {
std::shared_ptr<commu_node> node_tmp = std::make_shared<commu_node>();
node_tmp->from_ = from_tmp;
node_vec_.push_back(node_tmp);
return node_vec_[node_vec_.size() - 1];
}
std::vector<std::shared_ptr<commu_node>> node_vec_;
};
int main() {
spIuser user1 = std::make_shared<User1>("user1");
spIuser user2 = std::make_shared<User1>("user2");
spIuser user3 = std::make_shared<User1>("user3");
spIuser user4 = std::make_shared<User1>("user4");
spIuser user5 = std::make_shared<User1>("user5");
std::vector<spIuser> user_vec{user1, user2, user3, user4, user5};
std::shared_ptr<IMediator> mediator = std::make_shared<Mediator>(user_vec);
// mediator->init(user_vec);
// mediator->from(user1)->to(user2);
mediator->from(user1)->to(user2);
mediator->from(user2)->to(user3);
mediator->from(user3)->to(user4);
mediator->from(user4)->to(user5);
std::shared_ptr<Message> msg = std::make_shared<Message>();
msg->vec_char.push_back('a');
user1->send(msg);
std::cout << "-------------" << std::endl;
return 0;
}
/*
[user1] send <a> to: [user2]
[user2] send <a> to: [user3]
[user3] send <a> to: [user4]
[user4] send <a> to: [user5]
-------------
*/
上面的例子中,user1和user2两个模块通过中介者进行交互,user分别实现了send用来发送数据,recv来接受数据。它俩通过中介者进行通讯,在mediator类中,处理了两个模块的交互逻辑,在上面的例子中就是user1和user2之间互相发送接受消息。
优缺点(摘录于网络)
优点:
- 单一职责原则。你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
- 开闭原则。 你无需修改实际组件就能增加新的中介者。
- 你可以减轻应用中多个组件间的耦合情况。
- 你可以更方便地复用各个组件。
缺点:
- 当组件越来越多时,中介者类会变得很复杂,会处理很多逻辑。