重读设计模式——中介者
动机#
在面向对象的设计中,鼓励将行为封装到各自的对象中,这就会导致如果一个动作涉及多个类对象之间的互动时,往往导致类与类之间的关系错综复杂。显然,这不利于后续的维护和扩展。
中介者类似于“加一层”的思想,将涉及多个类对象之间的动作封装到中介者类中,由中介者进行协调控制,而其他的类对象只需要知道中介者这个类就可以了,执行动作时,不需要再去和其他类交互。
中介者形象上类似于一个货物中转中心,负责调配所有的中转方案。
示例#
还是用货物中转举例,现在我们有以下的几种货物到达了中转站,但入口只有一个,需要决定谁先进去,如果让这几种货物协商,那么每个货物对象都需要知道对象的存在,这无疑增大了对象间的耦合性。
class FruitGoods;
class ClothesGoods;
class SeafoodGoods;
于是我们选择让中介者来决定,所有货物到达后通知中介者,中介者再通知该货物等待多久后进入。
std::random_device seed;
std::default_random_engine eng(seed());
std::uniform_int_distribution<int> generator(1, 5);
class Goods;
class GoodsMediator {
public:
void registerGoods(Goods& goods) {
m_goodslist.push_back(goods);
}
int notify() {
return generator(eng);
}
private:
std::vector<Goods> m_goodslist{};
};
class Goods {
public:
Goods(GoodsMediator& mediator) : m_mediator(mediator) {
mediator.registerGoods(*this);
}
virtual void waitEnter() {
std::cout << "wait for " << m_mediator.notify() << " s\n";;
}
protected:
GoodsMediator& m_mediator;
};
class FruitGoods : public Goods {
public:
FruitGoods(GoodsMediator& mediator) : Goods(mediator) { }
void waitEnter() {
cout << "fruit: ";
Goods::waitEnter();
}
};
class ClothesGoods : public Goods {
public:
ClothesGoods(GoodsMediator& mediator) : Goods(mediator) { }
void waitEnter() {
cout << "clothes: ";
Goods::waitEnter();
}
};
class SeafoodGoods : public Goods {
public:
SeafoodGoods(GoodsMediator& mediator) : Goods(mediator) { }
void waitEnter() {
cout << "seafood: ";
Goods::waitEnter();
}
};
int main() {
GoodsMediator mediator;
FruitGoods fruit(mediator);
ClothesGoods clothes(mediator);
SeafoodGoods seafood(mediator);
fruit.waitEnter();
clothes.waitEnter();
seafood.waitEnter();
return 0;
}
结果可能如下:
fruit: wait for 3 s
clothes: wait for 2 s
seafood: wait for 4 s
通过加入了中介者这一层,货物之间的耦合性降低了,货物只需要知道中介者,并且将自己注册给中介者即可。
适用性#
- 一组对象通过一些定义良好但复杂的方式进行通讯,产生的依赖关系过于混乱而难以理解。
- 一个对象需要和多个对象直接通信,导致这个对象难以复用。
- 希望定制一些涉及多个类的行为,但是又不想生成太多的子类。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏