前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python设计模式(13):中介者模式

Python设计模式(13):中介者模式

作者头像
不可言诉的深渊
发布2019-07-26 17:38:27
5820
发布2019-07-26 17:38:27
举报
文章被收录于专栏:Python机器学习算法说书人

在现实生活中,有许多纠纷在人们之间不能协商解决,于是就产生了诸如商业仲裁等机构。商业仲裁的目的是避免当事人各方各执一词的直接交锋,而利用法律手段进行商业谈判。

中介者模式的概念与机制

一般地,一个软件系统包含一些对象,每个对象都可以提供一些服务。如果对象之间直接通过消息互相调用,当对象数目比较少时对象间的消息调用相对简单,如图所示。

但是随着参与对象变得越来越多时,调用关系变得越来越复杂,这将严重影响重复利用(因为高耦合度)。例如,当参与对象由 3 个增加到 5 个时,对象间两两交互的数目就由 6 个增加到 20 个,如图所示。

也就是说,虽然参与者的数目有较小的增加,但是交互的数目却增加很多。在这种情况下,可以利用中介者模式减少各个对象间的直接调用。

中介者模式的要点是将所有对象之间的交互细节抽象到一个独立的类中,这个类叫做中介者类 Mediator,如图所示。

每个对象仍然负责提供原来设计的服务,但是对象之间不再有之间交互,对象之间的交互经由 Mediator 类完成。为了完成某个任务,任何一个对象都可以给 Mediator 发送消息(调用 Mediator 的方法),Mediator 再给相关的有能力的合作完成该任务的对象发送消息(调用那些对象中的方法),最后完成一项任务。

例如,对象 B 调用 Mediator 的某个方法,而在这个方法中将调用对象 E、F、G 中的某些方法,也有可能反过来调用 B 的方法。对象 B 可能根本不知道哪个对象被调用了。

设计类图就是以上逻辑图的具体体现,叫做中介者模式设计类图,如图所示。

该设计类图由两部分组成,一部分是中介者类,另一部分是参与者对象。中介者模式的各组成部分的含义说明如下。

  1. Mediator:中介者接口。
  2. ConcreteMediator:具体的中介者。可以有多个具体的中介者,当只有一个中介者时,接口 Mediator 可以省略。
  3. Colleague:参与者对象接口。
  4. ConcreteColleague:具体的参与者。可以有多个具体的参与者。当只有一个参与者时,接口 Colleague 可以省略。

在“四人帮”(Gang of four,Gof)的书中,对于中介者模式的概念做了以下描述:中介者模式定义了一个对象,用来封装一系列对象的交互。中介者模式避免了对象之间的直接交互,从而提升了松耦合。中介者可以让用户独立的改变对象之间的交互(因为所有对象之间的交互都在 Mediator 类中进行)。

中介者模式的优点如下。

  1. 所有对象的交互行为都被转入到一个独立的中介者对象中,使得用户更容易通过中介者修改对象之间的相互关系行为。当修改一个交互行为的时候,可以通过修改或者更换其中一个具体的中介者子类来完成。另外,将对象的交互转移到一个专门的类中也提高了对象的可重用性。
  2. 因为对象之间不直接有交互,使对象的单元测试更加容易。
  3. 低耦合使得一个类的修改不会影响到其他的类。

中介者模式的实现细节

中介者设计模式的两个重要的部分就是 Mediator 类的设计与客户类的实现细节,现在将对它们加以介绍。

Mediator 类的设计

在该 Mediator 类中,需要保持所有参与者类的类型变量,还应该写出相关的注册方法,每个注册方法都将从参数传入的对象赋值给相应的变量。

这样,通过调用 Mediator 类的注册方法,可以将所有的参与者类对象都拉入到 Mediator 对象中来。然后在合适的时候,在 Mediator 类中调用任何参与者类的方法,以便完成一些所希望的功能。

Client 类的实现细节

在应用程序 Client 中,创建中介者 Mediator 类的对象和所需要的参与者对象,然后将所需要的参与者对象都注册到中介者对象之中。

在完成注册之后,在 Client 类中可以调用 Mediator 类中的一些方法;而在 Mediator 类的方法中,使用已经注册了的对象调用各个参与者类中的任何方法。

值得注意的是,参与者对象的注册可以在参与者类中完成。在此情况下,在客户类 Client 中就不必在出现有关的注册语句了。

代码语言:javascript
复制
from abc import ABC, abstractmethod


class Mediator(ABC):
    @abstractmethod
    def send(self, message, colleague):
        pass


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 Colleague(ABC):
    def __init__(self, mediator):
        self.mediator = mediator

    @abstractmethod
    def send(self, message):
        pass

    @abstractmethod
    def notify(self, message):
        pass


class ConcreteColleague1(Colleague):
    def send(self, message):
        self.mediator.send(message, self)

    def notify(self, message):
        print('ConcreteColleague1', message)


class ConcreteColleague2(Colleague):
    def send(self, message):
        self.mediator.send(message, self)

    def notify(self, message):
        print('ConcreteColleague2', message)


class Client:
    @staticmethod
    def main():
        mediator = ConcreteMediator()
        colleague1 = ConcreteColleague1(mediator)
        colleague2 = ConcreteColleague2(mediator)
        mediator.colleague1 = colleague1
        mediator.colleague2 = colleague2
        colleague1.send('colleague1')
        colleague2.send('colleague2')


if __name__ == '__main__':
    Client.main()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python机器学习算法说书人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档