调停者模式(Mediatornbsp;Pattern)
通常,面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成。当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点)。图31.1展示了当ObjectA和ObjectB之间彼此直接引用时的直接交互。
Figure 31.1: Point-to-Point Communication in the Case of Two Objects
当对象的数量增加时,这种直接交互会导致对象之间复杂的、混乱的引用(如图31.2)。这就会影响应用程序的可维护性。同时,因为对象之间的高耦合,当一个对象直接引用其他的对象时,缩小了这些对象的复用范围。
Figure 31.2: Point-toPoint Communication?Increased Number of Objects
在这种情况下,调停模式(Mediator Pattern)可以为这组对象设计一个控制、协调交互(交流)的模型,从而消除对象直接引用其他对象的需求。(如图31.3)
Figure 31.3: Object Interaction?Mediator as a Communication Hub
调停者模式(Mediator Pattern)推荐抽象所有对象交互的细节到一个独立的类,这个类就是调停者,它负责这组对象之间的交互。这组对象中的 每一个对象仍然负责提供它所具有的服务,但为了提供服务,对象之间不能直接彼此交互。两个不同对象之间的交互通过调停者(Mediator)进行路由。所 有的对象把消息发送给调停者(Mediator)。调停者(Mediator)依据应用程序的需求把消息再发送给相应的对象。这样的设计有以下主要的优 点:
(1) 随着所有对象的交互行为移到一个独立的对象中,通过调停者(Mediator)的子类替换调停者(Mediator)或者改变它的功能可以很容易的改变对象之间内部的关联行为。
(2) 将对象的内部依赖关系移到一个单独的对象,这样会提高对象的可用性。
(3) 因为对象不需要直接引用其他的对象,所以对象可以更容易的进行单元测试。
(4) 类之间的低耦合可以使类在不影响其他类的基础上进行修改。
调停者(Mediator)模式和外观(Façade)模式
在一些方面调停者(Mediator)模式和外观(Façade)模式有相似之处。表31.1列出了两种模式之间的相似点和不同点。
Table 31.1: 调停者(Mediator)模式和外观(Façade)模式
在讨论命令模式的时候,我们建立了两个实验应用程序,让我们从新回顾这些应用程序,看一看应用调停者(Mediator,)模式如何避免对象与对象之间的直接交互。
在前一章建立的FTP模拟客户应用程序有下面的客户UI组件(表31.2)
Table 31.2: List of User Interface Objects and the Associated Functionality
图31.4描述了不同UI对象之间的交互。
Figure 31.4: Object Interaction
为了使现存应用程序对客户更加友好,让我们考虑如下的较小的改进。
(1) 当UI第一次显示,除了Exit按钮的所有按钮都是disabled的。
(2) 当从显示本地文件系统的JList控件中选择文件名时:
A、 Upload和Delete按钮应该是enabled的。
B、 在远程文件系统中任何可选择的文件项目应该为不可选的(deselected).
C、 Download按钮应该是disabled的。
(3) 当从显示远程文件系统的JList控件中选择文件名时:
A、Download和Delete按钮应该是enabled的。
B、在本地文件系统中任何可选择的文件项目应该为不可选的(deselected).
C、Upload按钮应该是disabled的。
D、 当执行完必要的Upload/download操作之后,Upload、Download和Delete按钮应该为disabled的。同样,删除一个特 定的文件后,Delete按钮应该为disabled的,同时Upload、Download按钮应该为enabled的。本地的和远程的文件系统在执行 完Upload、Download和Delete操作后,应该进行刷新。
图31.5显示了对象之间交互的结果。
Figure 31.5: Object-to-Object Communication with Increased Direct Reference to Each Other
当更多的控件因增加功能而被添加,如重命名一个文件、FTP服务器连接、断开等,对象直接直接的交互在对象内部产生复杂的、混乱的对象引用。这很大程度上降低了应用程序的可维护性。
调停者模式可以被应用到这种情况,是一种对对象交互的高效的设计。应用调停者模式,一个描述对象之间交互细节的抽象被建立。这个抽象被设计为一个独立的Mediator类,如图31.6和Listing 31.1
Figure 31.6: Mediator
Listing 31.1: Mediator Class
从Mediator类的实现可以看到:Mediator为不同的UI对象提供了把它们自己注册到Mediator的方法。当每一个UI控件被激活(或者点击)时对象之间需要执行的一组交互被设计为Mediator内部的一个单独的方法。
客户使用调停者(Mediator)
客户(Listing31.2)创建一个Meditor的实例,当创建UI对象时,客户传递Mediator实例给它,UI对象通过这个Mediator实例注册它自身。
Listing 31.2: Client FTPGUI Class
用户接口对象--Mediator交互
因为所有的对象之间交互的细节从单独的UI对象移到了Mediator对象,每一个UI对象的processEvent方法简单到调用Mediator上的是当方法(listing 31.3)。图31.7显示了应用调停者模式以后,UI对象之间的交互。
Listing 31.3: Simplified UI Object Classes
Figure 31.7: Object Interaction?Mediator as a Communication Hub
在 讨论命令模式的时候,我们建立了一个增加和删除图书馆中项目数据库中项目的应用程序。一个给定的项目可以使一个或者多个分类的一部分。每一个Item对象 维护了它所属的分类的一个列表。同理,每一个Category对象也维护了一个它的所有项目的列表。图31.8是了这种类关联图。
Figure 31.8: Item-Category Association
当应用程序需要处理很多属于一个或者多个分类的项目时,对象之间的交互就会相当复杂。图31.9描述了当不同Item和Category对象彼此直接引用时的场景。
Figure 31.9: Item-Category Object Interaction
不同的Item和Category对象间的直接交互可以通过把对象的交互细节从Item和Category类移到一个单独的Mediator类中得到消除(图31.10)。Mediator可以设计为有以下两组方法:
(1) 一组可以允许不同的Item和Category对象注册到Mediator的方法。
(2) 一组可以增加和删除项目的方法。作为这些方法一部分的不同对象之间交互,由Mediator负责的实现。
Figure 31.10: Mediator
Mediator可以维护Item?Category的关联,Item对象不需要直接引用Catory对象。
因此,一个Item对象不需要维护一个它所属的Categories的列表。同样,增加和删除操作不需要在Item和Category类的内部实现。
AddCommand 和DeleteCommand Command对象的Execute方法只是分别调用Mediator类的addItem和deleteItem方法。
本文原码:
附件:36.rar(10K)
第31章:调停者模式(Mediator Pattern)
描述:
通常,面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成。当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点)。图31.1展示了当ObjectA和ObjectB之间彼此直接引用时的直接交互。
![31.1.bmp](http://www.javazy.com/members/stoneWindow/31.1.bmp)
Figure 31.1: Point-to-Point Communication in the Case of Two Objects
当对象的数量增加时,这种直接交互会导致对象之间复杂的、混乱的引用(如图31.2)。这就会影响应用程序的可维护性。同时,因为对象之间的高耦合,当一个对象直接引用其他的对象时,缩小了这些对象的复用范围。
![31.2.bmp](http://www.javazy.com/members/stoneWindow/31.2.bmp)
Figure 31.2: Point-toPoint Communication?Increased Number of Objects
在这种情况下,调停模式(Mediator Pattern)可以为这组对象设计一个控制、协调交互(交流)的模型,从而消除对象直接引用其他对象的需求。(如图31.3)
![31.3.bmp](http://www.javazy.com/members/stoneWindow/31.3.bmp)
Figure 31.3: Object Interaction?Mediator as a Communication Hub
调停者模式(Mediator Pattern)推荐抽象所有对象交互的细节到一个独立的类,这个类就是调停者,它负责这组对象之间的交互。这组对象中的 每一个对象仍然负责提供它所具有的服务,但为了提供服务,对象之间不能直接彼此交互。两个不同对象之间的交互通过调停者(Mediator)进行路由。所 有的对象把消息发送给调停者(Mediator)。调停者(Mediator)依据应用程序的需求把消息再发送给相应的对象。这样的设计有以下主要的优 点:
(1) 随着所有对象的交互行为移到一个独立的对象中,通过调停者(Mediator)的子类替换调停者(Mediator)或者改变它的功能可以很容易的改变对象之间内部的关联行为。
(2) 将对象的内部依赖关系移到一个单独的对象,这样会提高对象的可用性。
(3) 因为对象不需要直接引用其他的对象,所以对象可以更容易的进行单元测试。
(4) 类之间的低耦合可以使类在不影响其他类的基础上进行修改。
调停者(Mediator)模式和外观(Façade)模式
在一些方面调停者(Mediator)模式和外观(Façade)模式有相似之处。表31.1列出了两种模式之间的相似点和不同点。
Table 31.1: 调停者(Mediator)模式和外观(Façade)模式
![31.t1.bmp](http://www.javazy.com/members/stoneWindow/31.t1.bmp)
在讨论命令模式的时候,我们建立了两个实验应用程序,让我们从新回顾这些应用程序,看一看应用调停者(Mediator,)模式如何避免对象与对象之间的直接交互。
例子1:
在前一章建立的FTP模拟客户应用程序有下面的客户UI组件(表31.2)
![31.t2.bmp](http://www.javazy.com/members/stoneWindow/31.t2.bmp)
Table 31.2: List of User Interface Objects and the Associated Functionality
图31.4描述了不同UI对象之间的交互。
![31.4.bmp](http://www.javazy.com/members/stoneWindow/31.4.bmp)
Figure 31.4: Object Interaction
为了使现存应用程序对客户更加友好,让我们考虑如下的较小的改进。
(1) 当UI第一次显示,除了Exit按钮的所有按钮都是disabled的。
(2) 当从显示本地文件系统的JList控件中选择文件名时:
A、 Upload和Delete按钮应该是enabled的。
B、 在远程文件系统中任何可选择的文件项目应该为不可选的(deselected).
C、 Download按钮应该是disabled的。
(3) 当从显示远程文件系统的JList控件中选择文件名时:
A、Download和Delete按钮应该是enabled的。
B、在本地文件系统中任何可选择的文件项目应该为不可选的(deselected).
C、Upload按钮应该是disabled的。
D、 当执行完必要的Upload/download操作之后,Upload、Download和Delete按钮应该为disabled的。同样,删除一个特 定的文件后,Delete按钮应该为disabled的,同时Upload、Download按钮应该为enabled的。本地的和远程的文件系统在执行 完Upload、Download和Delete操作后,应该进行刷新。
图31.5显示了对象之间交互的结果。
![31.5.bmp](http://www.javazy.com/members/stoneWindow/31.5.bmp)
Figure 31.5: Object-to-Object Communication with Increased Direct Reference to Each Other
当更多的控件因增加功能而被添加,如重命名一个文件、FTP服务器连接、断开等,对象直接直接的交互在对象内部产生复杂的、混乱的对象引用。这很大程度上降低了应用程序的可维护性。
调停者模式可以被应用到这种情况,是一种对对象交互的高效的设计。应用调停者模式,一个描述对象之间交互细节的抽象被建立。这个抽象被设计为一个独立的Mediator类,如图31.6和Listing 31.1
![31.6.bmp](http://www.javazy.com/members/stoneWindow/31.6.bmp)
Figure 31.6: Mediator
Listing 31.1: Mediator Class
- class Mediator {
- private UploadButton btnUpload;
- private DownloadButton btnDownload;
- private DeleteButton btnDelete;
- private LocalList localList;
- private RemoteList remoteList;
- public void registerUploadButton(UploadButton inp_ib) {
- btnUpload = inp_ib;
- }
- public void registerDownloadButton(
- DownloadButton inp_dnb) {
- btnDownload = inp_dnb;
- }
- public void registerDeleteButton(DeleteButton inp_db) {
- btnDelete = inp_db;
- }
- public void registerLocalList(LocalList inp_arl) {
- localList = inp_arl;
- }
- public void registerRemoteList(RemoteList inp_drl) {
- remoteList = inp_drl;
- }
- public void UploadItem() {
- int index = localList.getSelectedIndex();
- String selectedItem =
- localList.getSelectedValue().toString();
- ((DefaultListModel) localList.getModel()).remove(
- index);
- ((DefaultListModel) remoteList.getModel()).addElement(
- selectedItem);
- btnUpload.setEnabled(false);
- btnDelete.setEnabled(false);
- btnDownload.setEnabled(false);
- }
- public void DownloadItem() {
- …
- …
- }
- public void DeleteItem() {
- …
- …
- }
- public void LocalListSelect() {
- …
- …
- }
- public void RemoteListSelect() {
- localList.setSelectedIndex(-1);
- btnUpload.setEnabled(false);
- btnDelete.setEnabled(true);
- btnDownload.setEnabled(true);
- }
- }
从Mediator类的实现可以看到:Mediator为不同的UI对象提供了把它们自己注册到Mediator的方法。当每一个UI控件被激活(或者点击)时对象之间需要执行的一组交互被设计为Mediator内部的一个单独的方法。
客户使用调停者(Mediator)
客户(Listing31.2)创建一个Meditor的实例,当创建UI对象时,客户传递Mediator实例给它,UI对象通过这个Mediator实例注册它自身。
Listing 31.2: Client FTPGUI Class
- public class FTPGUI extends JFrame {
- …
- …
- private Mediator mdtr = new Mediator();
- public FTPGUI() throws Exception {
- …
- …
- //Create controls
- defLocalList = new DefaultListModel();
- defRemoteList = new DefaultListModel();
- localList = new LocalList(defLocalList, mdtr);
- remoteList = new RemoteList(defRemoteList, mdtr);
- pnlFTPUI = new JPanel();
- …
- …
- //Create buttons
- UploadButton btnUpload =
- new UploadButton(FTPGUI.UPLOAD, mdtr);
- btnUpload.setMnemonic(KeyEvent.VK_U);
- DownloadButton btnDownload =
- new DownloadButton(FTPGUI.DOWNLOAD, mdtr);
- btnDownload.setMnemonic(KeyEvent.VK_N);
- DeleteButton btnDelete =
- new DeleteButton(FTPGUI.DELETE, mdtr);
- btnDelete.setMnemonic(KeyEvent.VK_D);
- …
- …
- }
- …
- …
- }//end of class
用户接口对象--Mediator交互
因为所有的对象之间交互的细节从单独的UI对象移到了Mediator对象,每一个UI对象的processEvent方法简单到调用Mediator上的是当方法(listing 31.3)。图31.7显示了应用调停者模式以后,UI对象之间的交互。
Listing 31.3: Simplified UI Object Classes
- …
- …
- class UploadButton extends JButton
- implements CommandInterface {
- Mediator mdtr;
- public void processEvent() {
- mdtr.UploadItem();
- }
- public UploadButton(String name, Mediator inp_mdtr) {
- super(name);
- mdtr = inp_mdtr;
- mdtr.registerUploadButton(this);
- }
- }
- class DownloadButton extends JButton
- implements CommandInterface {
- Mediator mdtr;
- public void processEvent() {
- mdtr.DownloadItem();
- }
- public DownloadButton(String name, Mediator inp_mdtr) {
- super(name);
- mdtr = inp_mdtr;
- mdtr.registerDownloadButton(this);
- }
- }
- …
- …
![31.7.bmp](http://www.javazy.com/members/stoneWindow/31.7.bmp)
Figure 31.7: Object Interaction?Mediator as a Communication Hub
例子2:
在 讨论命令模式的时候,我们建立了一个增加和删除图书馆中项目数据库中项目的应用程序。一个给定的项目可以使一个或者多个分类的一部分。每一个Item对象 维护了它所属的分类的一个列表。同理,每一个Category对象也维护了一个它的所有项目的列表。图31.8是了这种类关联图。
![31.8.bmp](http://www.javazy.com/members/stoneWindow/31.8.bmp)
Figure 31.8: Item-Category Association
当应用程序需要处理很多属于一个或者多个分类的项目时,对象之间的交互就会相当复杂。图31.9描述了当不同Item和Category对象彼此直接引用时的场景。
![31.9.bmp](http://www.javazy.com/members/stoneWindow/31.9.bmp)
Figure 31.9: Item-Category Object Interaction
不同的Item和Category对象间的直接交互可以通过把对象的交互细节从Item和Category类移到一个单独的Mediator类中得到消除(图31.10)。Mediator可以设计为有以下两组方法:
(1) 一组可以允许不同的Item和Category对象注册到Mediator的方法。
(2) 一组可以增加和删除项目的方法。作为这些方法一部分的不同对象之间交互,由Mediator负责的实现。
![31.10.bmp](http://www.javazy.com/members/stoneWindow/31.10.bmp)
Figure 31.10: Mediator
Mediator可以维护Item?Category的关联,Item对象不需要直接引用Catory对象。
因此,一个Item对象不需要维护一个它所属的Categories的列表。同样,增加和删除操作不需要在Item和Category类的内部实现。
AddCommand 和DeleteCommand Command对象的Execute方法只是分别调用Mediator类的addItem和deleteItem方法。
本文原码:
附件:36.rar(10K)
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-132258/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-132258/