设计模式~调停者模式(Mediator)
调停者模式是对象的行为模式。
调停者模式包装了一系列对象相互作用的方式,使得这些对象不必互相明显引用。
从而使它们可以比较松散的耦合。当这些对象中的某些对象之间的相互作用发生改变时,
不会立即影响到其他的一些对象之间的相互作用。从而保证这些相互作用可以彼此独立的变化。
不要滥用模式
要想恰到好处的在一个系统里面使用设计模式,必须做到以下几点:
1. 完全了解面临的问题,这就是说要完全了解具体情况。
2. 完全了解模式,这就是说要十分懂得理论。
3. 非常了解怎样使用设计模式解决实际问题,这就是说要将模式理论与具体系统需求情况相结合。
什么是调停者模式
在调停者模式中,所有的成员对象都可以协调工作,但是又不直接相互管理。
这些对象都与一个处于中心地位的调停者对象发生紧密的关系,由这个调停者对象进行协调工作。
这个协调者对象叫做调停者(Mediator),而调停者所协调的成员对象称作同事对象(Colleague)。
调停者模式的结构
调停者模式的角色:
- 抽象调停者模式:定义出同事对象到调停者对象的接口,其中主要的方法是一个(或者多个)事件方法。在有些情况下,这个抽象对象可以省略。一般而言,这个角色由一个Java抽象类或者Java对象实现。
- 具体调停者角色:从抽象调停者继承而来,实现了抽象超类所声明的事件方法。具体调停者知晓所有的具体同事类,它从具体同事对象接收消息,向具体同事对象发出命令。一般而言,这个角色由一个具体Java类实现。
- 抽象同事类角色:定义出调停者到同事对象的接口。同时对象只知道调停者而不知道其余的同事对象。一般而言,这个角色由一个Java抽象类或者Java对象实现。
- 具体同事类角色:所有的具体同事类均从抽象同事类继承而来。每一个具体同事类都清楚它自己在小范围内的行为,而不知道它在大范围内的目的。
下面是一个简化的示意性实现
代码清单:
抽象同事类
public abstract class Colleague {
private Mediator mediator;
public Colleague(Mediator m)
{
mediator = m;
}
public Mediator getMediator(){
return mediator;
}
public abstract void action();
public void change(){
mediator.colleagueChanged(this);
}
}
具体同事类
public class Colleague1 extends Colleague {
public Colleague1(Mediator m)
{
super(m);
}
/**
* 行动方法的具体实现
*/
public void action() {
System.out.println("This is an action from Colleague 1");
}
}
public class Colleague2 extends Colleague {
public Colleague2(Mediator m){
super(m);
}
public void action() {
// TODO Auto-generated method stub
System.out.println("This is an action from Colleague 2");
}
}
抽象调停者类
public abstract class Mediator {
//事件方法,由子类实现
public abstract void colleagueChanged(Colleague c);
public static void main(String[] args)
{
ConcreteMediator mediator = new ConcreteMediator();
mediator.createConcreteMediator();
Colleague c1 = new Colleague1(mediator);
Colleague c2 = new Colleague2(mediator);
mediator.colleagueChanged(c1);
}
}
具体调停者类
public class ConcreteMediator extends Mediator {
private Colleague1 colleague1;
private Colleague2 colleague2;
/**
* 事件方法的具体实现
*/
@Override
public void colleagueChanged(Colleague c) {
// TODO Auto-generated method stub
colleague1.action();
colleague2.action();
}
/**
* 工厂方法,创建同事对象
*/
public void createConcreteMediator(){
colleague1=new Colleague1(this);
colleague2 = new Colleague2(this);
}
public Colleague1 getColleague1(){
return colleague1;
}
public Colleague2 getColleague2(){
return colleague2;
}
}
调停者模式的时序
在某一个同事对象的状态发生变化时,这个同事对象需要通过调停者对象的事件方法通知其他的同事对象采取行动。
比如,Colleague1对象发生了状态变化,这时它调用Mediator对象的事件方法 colleagueChanged(), 并将自己作为参量传给Mediator对象;
后者则根据商业逻辑通过调用 Colleague1 和 Colleague2 的行动方法 action() 将这个信息传给所有有关的同事对象。
具体活动时序如下:
调停者模式的优点和缺点
优点:
1. 适当使用调停者模式可以较少使用静态的继承关系,使得具体同事类可以更加容易的被复用。
2. 适当使用调停者模式可以避免同事对象之间的过度耦合,使得调停类与同事类可以相对独立的演化。
3. 调停者模式将多对多的相互作用转化一对多的相互作用,使得对象之间的关系更加容易维护和理解。
4. 调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
缺点:
1. 调停者模式降低了同事对象的复杂性,代价是增加了调停者类的复杂性。当然,在很多情况下,设置一个调停者并不比不设置一个调停者更好。
2. 调停者类经常充满了各个具体同事类的关系协调代码,这种代码常常是不能复用的。因此,具体同事类的复用是以调停者类的不可复用为代价的。
显然,调停者模式为同事对象,而不是调停者对象提供了可扩展性,所以这个模式所提供的可扩展性是一种(向同事对象)倾斜的可扩展性。
调停者模式的使用条件
不应当在责任划分混乱时使用
不应当对数据类和方法类使用
正确理解封装
封装首先是行为,以及行为所涉及的状态的封装。行为与状态是不应当分割开来的。
调停者模式的用途是管理很多的对象的相互作用,以便使这些对象可以专注于自身的行为,而独立于其他的对象。
- history命令使用方法详解
- Linux删除乱码文件的方法
- 和智能机器一起工作,而不是惧怕它们
- Hulu大数据架构与应用经验
- SQL Server 2005:一个使用新创建的User的问题和解决方法
- Audit Logging-Stored Procedure
- Linux进程间通信(四) - 共享内存
- 扩展UltraGrid控件实现对所有数据行的全选功能[Source Code下载]
- Linux进程间通信(一) - 管道
- Linux进程间通信(二) - 消息队列
- Linux进程间通信(三) - 信号
- 我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
- Linux进程间通信(IPC)机制总览
- 负载均衡 - 综述
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 走进Golang之Context的使用
- 「Workshop」第十一期:降维
- 开始在 GitHub 上写博客
- 微信公众号菜单点击发送天气预报
- SAP CRM Fiori应用如何启用Sales Office和Sales Group两个字段
- 通过注册表调整 Windows 8 窗口边框宽度
- 在 Mac OS X 中创建和使用内存盘
- Mono for Android 下的 ListActivity
- 使用JavaScript Function.prototype进行代码重构的一些例子
- Activity 生命周期及其栈管理方式
- 如何操作SAP UI5应用Footer区域工具栏按钮的背景颜色
- 我的第一个 Mono for Android 应用
- 【DB笔试面试851】在Oracle中,造成“ORA-28040: No matching ...”错误的原因是什么?
- 在 Silverlight 5 项目中使用 async/await
- 开源一个 Sliverlight 导航框架