github地址:https://github.com/cheesezh/python_design_patterns

题目背景

联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对象之间的关系,这就要求对象之间需要知道其他所有对象,尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增优惠降低其可复用性。大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难了。

这里可以应用“迪米特法则”,如果两个类不必彼此直接通讯,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一种方法的话,可以通过第三者转发这个调用。也就是说,国与国之间的关系,完全可以通过联合国这个中介者来维持,而不必直接通信。

中介者模式

中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显示的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。[DP]

中介者模式主要包括以下几个类:

  • Colleague叫做抽象同事类,而ConcretColleague是具体同事类,每个具体同事只知道自己的行为,而不了解其他同事类的情况,但它们却都认识中介者对象;
  • Mediator是抽象中介者,定义了同事对象到中介者对象的接口,ConcretMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令。
from abc import ABCMeta, abstractmethod

class Mediator():
"""
抽象中介者
""" __metaclass__ = ABCMeta @abstractmethod
def send(self, message, colleague):
"""
定义一个抽象的发送消息方法,得到同事对象和发送消息
"""
pass class Colleague():
"""
抽象同事类
""" __metaclass__ = ABCMeta def __init__(self, mediator):
"""
构造方法,得到中介者对象
"""
self.mediator = mediator class ConcreteMediator(Mediator):
"""
具体中介者
"""
def __init__(self):
"""
需要了解所有的具体同事对象
"""
self.colleague1 = None
self.colleague2 = None def send(self, message, colleague):
"""
重写发送消息的方法,根据对象作出选择判断,通知具体同事对象
"""
if colleague == self.colleague1:
self.colleague2.notify(message)
else:
self.colleague1.notify(message) class ConcreteColleague1(Colleague):
"""
具体同事类1
"""
def send(self, message):
self.mediator.send(message, self) def notify(self, message):
print("同事1得到消息:",message) class ConcreteColleague2(Colleague):
"""
具体同事类2
"""
def send(self, message):
self.mediator.send(message, self) def notify(self, message):
print("同事2得到消息:",message) def main():
m = ConcreteMediator() """
让两个具体同事类认识中介者对象
"""
c1 = ConcreteColleague1(m)
c2 = ConcreteColleague2(m) """
让中介者认识各个具体同事类
"""
m.colleague1 = c1
m.colleague2 = c2 """
具体同事类对象发送消息都是通过中介者转发
"""
c1.send("吃饭了吗?")
c2.send("还没,你请客么?") main()
同事2得到消息: 吃饭了吗?
同事1得到消息: 还没,你请客么?

点评

由于有了Mediator,使得ConcreteColleague1和ConcreteColleague2在发送消息和接收消息时其实是通过中介者来完成,这就减少了它们之间的耦合度。

题目

用程序模拟,美国和伊拉克之间的对话都是通过联合国安理会作为中介来完成。

from abc import ABCMeta, abstractmethod

class UnitedNations():
"""
联合国机构,抽象中介者
""" __metaclass__ = ABCMeta @abstractmethod
def send(self, message, colleague):
"""
定义一个抽象的发送消息方法,得到同事对象和发送消息
"""
pass class Country():
"""
国家类,抽象同事类
""" __metaclass__ = ABCMeta def __init__(self, mediator):
"""
构造方法,得到中介者对象
"""
self.mediator = mediator class UnitedNationsSecurityCouncil(Mediator):
"""
联合国安全理事会,具体中介者
"""
def __init__(self):
"""
需要了解所有的具体同事对象
"""
self.colleague1 = None
self.colleague2 = None def send(self, message, colleague):
"""
重写发送消息的方法,根据对象作出选择判断,通知具体同事对象
"""
if colleague == self.colleague1:
self.colleague2.notify(message)
else:
self.colleague1.notify(message) class USA(Colleague):
"""
美国,具体同事类1
"""
def send(self, message):
self.mediator.send(message, self) def notify(self, message):
print("美国 得到消息:",message) class Iraq(Colleague):
"""
伊拉克,具体同事类2
"""
def send(self, message):
self.mediator.send(message, self) def notify(self, message):
print("伊拉克 得到消息:",message) def main():
m = UnitedNationsSecurityCouncil() """
让两个具体同事类认识中介者对象
"""
c1 = USA(m)
c2 = Iraq(m) """
让中介者认识各个具体同事类
"""
m.colleague1 = c1
m.colleague2 = c2 """
具体同事类对象发送消息都是通过中介者转发
"""
c1.send("吃饭了吗?")
c2.send("还没,你请客么?") main()
伊拉克 得到消息: 吃饭了吗?
美国 得到消息: 还没,你请客么?

点评

ConcretMediator这个类必须要知道所有ConcreteCollegue,这就使得ConcreteMediator责任太多,如果它出现问题,则整个系统都会出现问题。

中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现“多对多”交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是否合理。

中介者模式的优点:

  • Mediator的出现减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague类和Mediator;
  • 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。

中介者模式的缺点:

  • 由于ConcreteMediator控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。

[Python设计模式] 第25章 联合国维护世界和平——中介者模式的更多相关文章

  1. [Python设计模式] 第23章 烤串的哲学——命令模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟,顾客直接向烤串师傅提需求. class Barbecuer( ...

  2. [Python设计模式] 第22章 手机型号&软件版本——桥接模式

    github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...

  3. [Python设计模式] 第12章 基金理财更省事——外观模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...

  4. [Python设计模式] 第2章 商场收银软件——策略模式

    github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...

  5. [Python设计模式] 第10章 怎么出试卷?——模版方法模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 小时候数学老师的随堂测验,都是老师在黑板上写题目,学生在下边抄,然后再做题 ...

  6. [Python设计模式] 第1章 计算器——简单工厂模式

    github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...

  7. [Python设计模式] 第21章 计划生育——单例模式

    github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...

  8. [Python设计模式] 第26章 千人千面,内在共享——享元模式

    github地址:https://github.com/cheesezh/python_design_patterns 背景 有6个客户想做产品展示网站,其中3个想做成天猫商城那样的"电商风 ...

  9. [Python设计模式] 第27章 正则表达式——解释器模式

    github地址:https://github.com/cheesezh/python_design_patterns 解释器模式 解释器模式,给定一个语言,定一个它的文法的一种表示,并定一个一个解释 ...

随机推荐

  1. BZOJ1856 [Scoi2010]字符串 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8084577.html 题目传送门 - BZOJ1856 题意概括 找出由n个1,m个0组成的字符串,且任意前几个 ...

  2. 51nod1967 路径定向 Fleury

    题目传送门 题解 几乎是Fleury模板题. 一开始我们把图看作无向图,然后对于度为奇数的点增边,使得整个图的所有点都是偶数的. 然后跑一遍欧拉回路 Fleury ,所有的边就定向好了~ 代码 #in ...

  3. 第四周java学习笔记

    1.封装 封装可以理解为把方法封在类中,用打时候可以直接拿,就好比你要上学,类就是书包而方法就是书,要用方法打时候直接从书包中拿书就行. 2.类语法细节 public权限修饰 public是个公开类, ...

  4. Redis的工作流程

    从图上可以看出,当一个客户端访问服务器的时候,客户端请求会先到达Nginx,由Nginx负责对数据进行分发,上传到多个服务器,当用户访问到tomcat1的时候,会进行登陆验证并将session放入se ...

  5. TF之RNN:实现利用scope.reuse_variables()告诉TF想重复利用RNN的参数的案例—Jason niu

    import tensorflow as tf # 22 scope (name_scope/variable_scope) from __future__ import print_function ...

  6. TF之RNN:基于顺序的RNN分类案例对手写数字图片mnist数据集实现高精度预测—Jason niu

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_dat ...

  7. P3353 在你窗外闪耀的星星

    飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀着你玫瑰色的脸颊.我明 ...

  8. 005.Ceph文件系统基础使用

    一 Ceph文件系统 1.1 概述 CephFS也称ceph文件系统,是一个POSIX兼容的分布式文件系统. 实现ceph文件系统的要求: 需要一个已经正常运行的ceph集群: 至少包含一个ceph元 ...

  9. Django 学习第四天——Django 模板标签

    一.模板标签: 作用:标签在渲染的过程中提供任意的逻辑:例如 if for...in... 等 标签语法:由 {% %} 来定义的:例如:{% tag %}xxx{% endtag %} 常用标签: ...

  10. BZOJ.3938.Robot(李超线段树)

    BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...