# 协调多个对象之间的交互——中介者模式(一)
腾讯公司推出的QQ作为一款免费的即时聊天软件深受广大用户的喜爱,它已经成为很多人学习、工作和生活的一部分(不要告诉我你没有QQ哦)。在QQ聊天中,一般有两种聊天方式:第一种是用户与用户直接聊天,第二种是通过QQ群聊天,如图20-1所示。如果我们使用图20-1(A)所示方式,一个用户如果要与别的用户聊天或发送文件,通常需要加其他用户为好友,用户与用户之间存在多对多的联系,这将导致系统中用户之间的关系非常复杂,一个用户如果要将相同的信息或文件发送给其他所有用户,必须一个一个的发送,于是QQ群产生了,如图20-1(B)所示,如果使用QQ群,一个用户就可以向多个用户发送相同的信息和文件而无须一一进行发送,只需要将信息或文件发送到群中或作为群共享即可,群的作用就是将发送者所发送的信息和文件转发给每一个接收者用户。通过引入群的机制,将极大减少系统中用户之间的两两通信,用户与用户之间的联系可以通过群来实现。
![](http://img.my.csdn.net/uploads/201301/08/1357651347_7261.jpg)
图20-1 QQ聊天示意图
在有些软件中,某些类/对象之间的相互调用关系错综复杂,类似QQ用户之间的关系,此时,我们特别需要一个类似“QQ群”一样的中间类来协调这些类/对象之间的复杂关系,以降低系统的耦合度。有一个设计模式正为此而诞生,它就是本章将要介绍的中介者模式。
20.1 客户信息管理窗口的初始设计
Sunny软件公司欲开发一套CRM系统,其中包含一个客户信息管理模块,所设计的“客户信息管理窗口”界面效果图如图20-2所示:
![](http://img.my.csdn.net/uploads/201301/08/1357651353_4861.jpg)
图20-2 “客户信息管理窗口”界面图
Sunny公司开发人员通过分析发现,在图20-2中,界面组件之间存在较为复杂的交互关系:如果删除一个客户,要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名称也将减少一个;如果增加一个客户信息,客户列表中需增加一个客户,且组合框中也将增加一项。
如果实现界面组件之间的交互是Sunny公司开发人员必须面对的一个问题?
Sunny公司开发人员对组件之间的交互关系进行了分析,结果如下:
(1) 当用户单击“增加”按钮、“删除”按钮、“修改”按钮或“查询”按钮时,界面左侧的“客户选择组合框”、“客户列表”以及界面中的文本框将产生响应。
(2) 当用户通过“客户选择组合框”选中某个客户姓名时,“客户列表”和文本框将产生响应。
(3) 当用户通过“客户列表”选中某个客户姓名时,“客户选择组合框”和文本框将产生响应。
于是,Sunny公司开发人员根据组件之间的交互关系绘制了如图20-3所示初始类图:
![](http://img.my.csdn.net/uploads/201301/08/1357651371_8838.jpg)
图20-3 “客户信息管理窗口”原始类图
与类图20-3所对应的框架代码片段如下:
```
//按钮类
class Button {
private List list;
private ComboBox cb;
private TextBox tb;
......
//界面组件的交互
public void change() {
list.update();
cb.update();
tb.update();
}
public void update() {
......
}
......
}
//列表框类
class List {
private ComboBox cb;
private TextBox tb;
......
//界面组件的交互
public void change() {
cb.update();
tb.update();
}
public void update() {
......
}
......
}
//组合框类
class ComboBox {
private List list;
private TextBox tb;
......
//界面组件的交互
public void change() {
list.update();
tb.update();
}
public void update() {
......
}
......
}
//文本框类
class TextBox {
public void update() {
......
}
......
}
```
分析图20-3所示初始结构图和上述代码,我们不难发现该设计方案存在如下问题:
(1) 系统结构复杂且耦合度高:每一个界面组件都与多个其他组件之间产生相互关联和调用,若一个界面组件对象发生变化,需要跟踪与之有关联的其他所有组件并进行处理,系统组件之间呈现一种较为复杂的网状结构,组件之间的耦合度高。
(2) 组件的可重用性差:由于每一个组件和其他组件之间都具有很强的关联,若没有其他组件的支持,一个组件很难被另一个系统或模块重用,这些组件表现出来更像一个不可分割的整体,而在实际使用时,我们往往需要每一个组件都能够单独重用,而不是重用一个由多个组件组成的复杂结构。
(3) 系统的可扩展性差:如果在上述系统中增加一个新的组件类,则必须修改与之交互的其他组件类的源代码,将导致多个类的源代码需要修改,同样,如果要删除一个组件也存在类似的问题,这违反了“开闭原则”,可扩展性和灵活性欠佳。
> 由于存在上述问题,Sunny公司开发人员不得不对原有系统进行重构,那如何重构呢?大家想到了“迪米特法则”,引入一个“第三者”来降低现有系统中类之间的耦合度。由这个“第三者”来封装并协调原有组件两两之间复杂的引用关系,使之成为一个松耦合的系统,这个“第三者”又称为“中介者”,中介者模式因此而得名。下面让我们正式进入中介者模式的学习,学会如何使用中介者类来协调多个类/对象之间的交互,以达到降低系统耦合度的目的。
- Introduction
- 基础知识
- 设计模式概述
- 从招式与内功谈起——设计模式概述(一)
- 从招式与内功谈起——设计模式概述(二)
- 从招式与内功谈起——设计模式概述(三)
- 面向对象设计原则
- 面向对象设计原则之单一职责原则
- 面向对象设计原则之开闭原则
- 面向对象设计原则之里氏代换原则
- 面向对象设计原则之依赖倒转原则
- 面向对象设计原则之接口隔离原则
- 面向对象设计原则之合成复用原则
- 面向对象设计原则之迪米特法则
- 六个创建型模式
- 简单工厂模式-Simple Factory Pattern
- 工厂三兄弟之简单工厂模式(一)
- 工厂三兄弟之简单工厂模式(二)
- 工厂三兄弟之简单工厂模式(三)
- 工厂三兄弟之简单工厂模式(四)
- 工厂方法模式-Factory Method Pattern
- 工厂三兄弟之工厂方法模式(一)
- 工厂三兄弟之工厂方法模式(二)
- 工厂三兄弟之工厂方法模式(三)
- 工厂三兄弟之工厂方法模式(四)
- 抽象工厂模式-Abstract Factory Pattern
- 工厂三兄弟之抽象工厂模式(一)
- 工厂三兄弟之抽象工厂模式(二)
- 工厂三兄弟之抽象工厂模式(三)
- 工厂三兄弟之抽象工厂模式(四)
- 工厂三兄弟之抽象工厂模式(五)
- 单例模式-Singleton Pattern
- 确保对象的唯一性——单例模式 (一)
- 确保对象的唯一性——单例模式 (二)
- 确保对象的唯一性——单例模式 (三)
- 确保对象的唯一性——单例模式 (四)
- 确保对象的唯一性——单例模式 (五)
- 原型模式-Prototype Pattern
- 对象的克隆——原型模式(一)
- 对象的克隆——原型模式(二)
- 对象的克隆——原型模式(三)
- 对象的克隆——原型模式(四)
- 建造者模式-Builder Pattern
- 复杂对象的组装与创建——建造者模式(一)
- 复杂对象的组装与创建——建造者模式(二)
- 复杂对象的组装与创建——建造者模式(三)
- 七个结构型模式
- 适配器模式-Adapter Pattern
- 不兼容结构的协调——适配器模式(一)
- 不兼容结构的协调——适配器模式(二)
- 不兼容结构的协调——适配器模式(三)
- 不兼容结构的协调——适配器模式(四)
- 桥接模式-Bridge Pattern
- 处理多维度变化——桥接模式(一)
- 处理多维度变化——桥接模式(二)
- 处理多维度变化——桥接模式(三)
- 处理多维度变化——桥接模式(四)
- 组合模式-Composite Pattern
- 树形结构的处理——组合模式(一)
- 树形结构的处理——组合模式(二)
- 树形结构的处理——组合模式(三)
- 树形结构的处理——组合模式(四)
- 树形结构的处理——组合模式(五)
- 装饰模式-Decorator Pattern
- 扩展系统功能——装饰模式(一)
- 扩展系统功能——装饰模式(二)
- 扩展系统功能——装饰模式(三)
- 扩展系统功能——装饰模式(四)
- 外观模式-Facade Pattern
- 深入浅出外观模式(一)
- 深入浅出外观模式(二)
- 深入浅出外观模式(三)
- 享元模式-Flyweight Pattern
- 实现对象的复用——享元模式(一)
- 实现对象的复用——享元模式(二)
- 实现对象的复用——享元模式(三)
- 实现对象的复用——享元模式(四)
- 实现对象的复用——享元模式(五)
- 代理模式-Proxy Pattern
- 设计模式之代理模式(一)
- 设计模式之代理模式(二)
- 设计模式之代理模式(三)
- 设计模式之代理模式(四)
- 十一个行为型模式
- 职责链模式-Chain of Responsibility Pattern
- 请求的链式处理——职责链模式(一)
- 请求的链式处理——职责链模式(二)
- 请求的链式处理——职责链模式(三)
- 请求的链式处理——职责链模式(四)
- 命令模式-Command Pattern
- 请求发送者与接收者解耦——命令模式(一)
- 请求发送者与接收者解耦——命令模式(二)
- 请求发送者与接收者解耦——命令模式(三)
- 请求发送者与接收者解耦——命令模式(四)
- 请求发送者与接收者解耦——命令模式(五)
- 请求发送者与接收者解耦——命令模式(六)
- 解释器模式-Interpreter Pattern
- 自定义语言的实现——解释器模式(一)
- 自定义语言的实现——解释器模式(二)
- 自定义语言的实现——解释器模式(三)
- 自定义语言的实现——解释器模式(四)
- 自定义语言的实现——解释器模式(五)
- 自定义语言的实现——解释器模式(六)
- 迭代器模式-Iterator Pattern
- 遍历聚合对象中的元素——迭代器模式(一)
- 遍历聚合对象中的元素——迭代器模式(二)
- 遍历聚合对象中的元素——迭代器模式(三)
- 遍历聚合对象中的元素——迭代器模式(四)
- 遍历聚合对象中的元素——迭代器模式(五)
- 遍历聚合对象中的元素——迭代器模式(六)
- 中介者模式-Mediator Pattern
- 协调多个对象之间的交互——中介者模式(一)
- 协调多个对象之间的交互——中介者模式(二)
- 协调多个对象之间的交互——中介者模式(三)
- 协调多个对象之间的交互——中介者模式(四)
- 协调多个对象之间的交互——中介者模式(五)
- 备忘录模式-Memento Pattern
- 撤销功能的实现——备忘录模式(一)
- 撤销功能的实现——备忘录模式(二)
- 撤销功能的实现——备忘录模式(三)
- 撤销功能的实现——备忘录模式(四)
- 撤销功能的实现——备忘录模式(五)
- 观察者模式-Observer Pattern
- 对象间的联动——观察者模式(一)
- 对象间的联动——观察者模式(二)
- 对象间的联动——观察者模式(三)
- 对象间的联动——观察者模式(四)
- 对象间的联动——观察者模式(五)
- 对象间的联动——观察者模式(六)
- 状态模式-State Pattern
- 处理对象的多种状态及其相互转换——状态模式(一)
- 处理对象的多种状态及其相互转换——状态模式(二)
- 处理对象的多种状态及其相互转换——状态模式(三)
- 处理对象的多种状态及其相互转换——状态模式(四)
- 处理对象的多种状态及其相互转换——状态模式(五)
- 处理对象的多种状态及其相互转换——状态模式(六)
- 策略模式-Strategy Pattern
- 算法的封装与切换——策略模式(一)
- 算法的封装与切换——策略模式(二)
- 算法的封装与切换——策略模式(三)
- 算法的封装与切换——策略模式(四)
- 模板方法模式-Template Method Pattern
- 模板方法模式深度解析(一)
- 模板方法模式深度解析(二)
- 模板方法模式深度解析(三)
- 访问者模式-Visitor Pattern
- 操作复杂对象结构——访问者模式(一)
- 操作复杂对象结构——访问者模式(二)
- 操作复杂对象结构——访问者模式(三)
- 操作复杂对象结构——访问者模式(四)
- 设计模式趣味学习(复习)
- 设计模式与足球(一)
- 设计模式与足球(二)
- 设计模式与足球(三)
- 设计模式与足球(四)
- 设计模式综合应用实例
- 多人联机射击游戏
- 多人联机射击游戏中的设计模式应用(一)
- 多人联机射击游戏中的设计模式应用(二)
- 数据库同步系统
- 设计模式综合实例分析之数据库同步系统(一)
- 设计模式综合实例分析之数据库同步系统(二)
- 设计模式综合实例分析之数据库同步系统(三)