`
chjavach
  • 浏览: 460975 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

研磨设计模式 之 中介者模式(Mediator)2 ——跟着cc学设计系列

 
阅读更多

 

10.2  解决方案

10.2.1  中介者模式来解决

用来解决上述问题的一个合理的解决方案就是中介者模式。那么什么是中介者模式呢?

(1)中介者模式定义

 

(2)应用中介者模式来解决的思路

仔细分析上面的问题,根本原因就在于多个对象需要相互交互,从而导致对象之间紧密耦合,这就不利于对象的修改和维护。

中介者模式的解决思路很简单,跟电脑的例子一样,中介者模式通过引入一个中介对象,让其它的对象都只和中介对象交互,而中介对象知道如何和其它所有的对象交互,这样对象之间的交互关系就没有了,从而实现对象之间的解耦。

对于中介对象而言,所有相互交互的对象,被视为同事类,中介对象就是来维护各个同事之间的关系,而所有的同事类都只是和中介对象交互。

每个同事对象,当自己发生变化的时候,不需要知道这会引起其它对象有什么变化,它只需要通知中介者就可以了,然后由中介者去与其它对象交互。这样松散耦合带来的好处是,除了让同事对象之间相互没有关联外,还有利于功能的修改和扩展。

有了中介者过后,所有的交互都封装到中介者对象里面,各个对象就不再需要维护这些关系了。扩展关系的时候也只需要扩展或修改中介者对象就可以了。

10.2.2  模式结构和说明

中介者模式的结构如图10.3所示:

 

图10.3  中介者模式结构示意图

Mediator

       中介者接口。在里面定义各个同事之间交互需要的方法,可以是公共的通讯方法,比如changed方法,大家都用,也可以是小范围的交互方法。

ConcreteMediator

       具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。

Colleague

       同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如:每个具体同事类都应该知道中介者对象,也就是具体同事类都会持有中介者对象,就可以定义到这个类里面。

ConcreteColleague

具体的同事类,实现自己的业务,在需要与其它同事通讯的时候,就与持有的中介者通信,中介者会负责与其它的同事交互。

10.2.3  中介者模式示例代码

(1)先来看看所有同事的父类的定义

按照前面的描述,所有需要交互的对象,都被视为同事类,这些同事类应该有一个统一的约束。而且所有的同事类都需要和中介者对象交互,换句话说就是所有的同事都应该持有中介者对象。

因此,为了统一约束众多的同事类,并为同事类提供持有中介者对象的公共功能,先来定义一个抽象的同事类,在里面实现持有中介者对象的公共功能。

要提醒一点,下面示例的这个抽象类是没有定义抽象方法的,主要是用来约束所有同事类的类型,示例代码如下:

/**

 * 同事类的抽象父类

 */

public abstract class Colleague {

    /**

     * 持有中介者对象,每一个同事类都知道它的中介者对象

     */

    private Mediator mediator;

    /**

     * 构造方法,传入中介者对象

     * @param mediator 中介者对象

     */

    public Colleague(Mediator mediator) {

       this.mediator = mediator;

    }

    /**

     * 获取当前同事类对应的中介者对象

     * @return 对应的中介者对象

     */

    public Mediator getMediator() {

       return mediator;

    }

}

(2)接下来看看具体的同事类,在示意中它们的实现是差不多的,示例代码如下:

/**

 * 具体的同事类A

 */

public class ConcreteColleagueA extends Colleague {

    public ConcreteColleagueA(Mediator mediator) {

       super(mediator);

    }

    /**

     * 示意方法,执行某些业务功能

     */

    public void someOperation() {

       //在需要跟其它同事通信的时候,通知中介者对象

       getMediator().changed(this);

    }

}

       同事类B的实现,示例代码如下:

/**

 * 具体的同事类B

 */

public class ConcreteColleagueB extends Colleague {

    public ConcreteColleagueB(Mediator mediator) {

       super(mediator);

    }

    /**

     * 示意方法,执行某些业务功能

     */

    public void someOperation() {

       //在需要跟其它同事通信的时候,通知中介者对象

       getMediator().changed(this);

    }

}

(3)接下来看看中介者的定义,示例代码如下:

/**

 * 中介者,定义各个同事对象通信的接口

 */

public interface Mediator {

    /**

     * 同事对象在自身改变的时候来通知中介者的方法,

     * 让中介者去负责相应的与其它同事对象的交互

     * @param colleague 同事对象自身,好让中介者对象通过对象实例

     *                     去获取同事对象的状态

     */

    public void changed(Colleague colleague);

}

(4)接下来看看具体的中介者实现,示例代码如下:

/**

 * 具体的中介者实现

 */

public class ConcreteMediator implements Mediator {

    /**

     * 持有并维护同事A

     */

    private ConcreteColleagueA colleagueA;

    /**

     * 持有并维护同事B

     */

    private ConcreteColleagueB colleagueB;

 

    /**

     * 设置中介者需要了解并维护的同事A对象

     * @param colleague 同事A对象

     */

    public void setConcreteColleagueA(

ConcreteColleagueA colleague) {

       colleagueA = colleague;

    }

    /**

     * 设置中介者需要了解并维护的同事B对象

     * @param colleague 同事B对象

     */

    public void setConcreteColleagueB(

ConcreteColleagueB colleague) {

       colleagueB = colleague;

    }  

 

    public void changed(Colleague colleague) {

       //某个同事类发生了变化,通常需要与其它同事交互

       //具体协调相应的同事对象来实现协作行为

    }

}

10.2.4  使用中介者模式来实现示例

要使用中介者模式来实现示例,那就要区分出同事对象和中介者对象。很明显,主板是作为中介者,而光驱、CPU、声卡、显卡等配件,都是作为同事对象。

根据中介者模式的知识,设计出示例的程序结构如图10.4所示:

 

图10.4  使用中介者模式实现示例的结构示意图

还是来看看代码实现,会更清楚。

(1)先来看看所有同事的抽象父类的定义,跟标准的实现是差不多的,示例代码如下:

public abstract class Colleague {

    private Mediator mediator;

    public Colleague(Mediator mediator) {

       this.mediator = mediator;

    }

    public Mediator getMediator() {

       return mediator;

    }

}

(2)定义众多的同事

定义好了同事的抽象父类,接下来就应该具体的实现这些同事类了,按照顺序一个一个来,先看看光驱类吧,示例代码如下:

/**

 * 光驱类,一个同事类

 */

public class CDDriver extends Colleague{

    public CDDriver(Mediator mediator) {

       super(mediator);

    }

    /**

     * 光驱读取出来的数据

     */

    private String data = "";

    /**

     * 获取光驱读取出来的数据

     * @return 光驱读取出来的数据

     */

    public String getData(){

       return this.data;

    }

    /**

     * 读取光盘

     */

    public void readCD(){

       //逗号前是视频显示的数据,逗号后是声音

       this.data = "设计模式,值得好好研究";

       //通知主板,自己的状态发生了改变

       this.getMediator().changed(this);

    }

}

接下来该看看CPU类了,示例代码如下:

/**

 * CPU类,一个同事类

 */

public class CPU extends Colleague{

    public CPU(Mediator mediator) {

       super(mediator);

    }

    /**

     * 分解出来的视频数据

     */

    private String videoData = "";

    /**

     * 分解出来的声音数据

     */

    private String soundData = "";

    /**

     * 获取分解出来的视频数据

     * @return 分解出来的视频数据

     */

    public String getVideoData() {

       return videoData;

    }

    /**

     * 获取分解出来的声音数据

     * @return 分解出来的声音数据

     */

    public String getSoundData() {

       return soundData;

    }

    /**

     * 处理数据,把数据分成音频和视频的数据

     * @param data 被处理的数据

     */

    public void executeData(String data){

       //把数据分解开,前面的是视频数据,后面的是音频数据

       String [] ss = data.split(",");

       this.videoData = ss[0];

       this.soundData = ss[1];

       //通知主板,CPU的工作完成

       this.getMediator().changed(this);

    }

}

该来看看显示的同事类了,显卡类的示例代码如下:

/**

 * 显卡类,一个同事类

 */

public class VideoCard extends Colleague{

    public VideoCard(Mediator mediator) {

       super(mediator);

    }

    /**

     * 显示视频数据

     * @param data 被显示的数据

     */

    public void showData(String data){

       System.out.println("您正观看的是:"+data);

    }

}

同样的,看看声卡的处理类,示例代码如下:

/**

 * 声卡类,一个同事类

 */

public class SoundCard extends Colleague{

    public SoundCard(Mediator mediator) {

       super(mediator);

    }

    /**

     * 按照声频数据发出声音

     * @param data 发出声音的数据

     */

    public void soundData(String data){

       System.out.println("画外音:"+data);

    }

}

(3)定义中介者接口

由于所有的同事对象都要和中介者交互,来定义出中介者的接口,功能不多,提供一个让同事对象在自身改变的时候来通知中介者的方法,示例代码如下:

/**

 * 中介者对象的接口

 */

public interface Mediator {

    /**

     * 同事对象在自身改变的时候来通知中介者的方法,

     * 让中介者去负责相应的与其它同事对象的交互

     * @param colleague 同事对象自身,好让中介者对象通过对象实例

     *                  去获取同事对象的状态

     */

    public void changed(Colleague colleague);

}

(4)实现中介者对象

中介者的功能就稍微多一点,它需要处理所有的同事对象之间的交互,好在我们要示例的东西并不麻烦,仅有两个功能处理而已,示例代码如下:

/**

 * 主板类,实现中介者接口

 */

public class MotherBoard implements Mediator{

    /**

     * 需要知道要交互的同事类——光驱类

     */

    private CDDriver cdDriver = null;

    /**

     * 需要知道要交互的同事类——CPU类

     */

    private CPU cpu = null;

    /**

     * 需要知道要交互的同事类——显卡类

     */

    private VideoCard videoCard = null;

    /**

     * 需要知道要交互的同事类——声卡类

     */

    private SoundCard soundCard = null;

 

    public void setCdDriver(CDDriver cdDriver) {

       this.cdDriver = cdDriver;

    }

    public void setCpu(CPU cpu) {

       this.cpu = cpu;

    }

    public void setVideoCard(VideoCard videoCard) {

       this.videoCard = videoCard;

    }

    public void setSoundCard(SoundCard soundCard) {

       this.soundCard = soundCard;

    }

    public void changed(Colleague colleague) {

       if(colleague == cdDriver){

           //表示光驱读取数据了

           this.opeCDDriverReadData((CDDriver)colleague);

       }else if(colleague == cpu){

           //表示CPU处理完了

           this.opeCPU((CPU)colleague);

       }

    }

    /**

     * 处理光驱读取数据过后与其它对象的交互

     * @param cd 光驱同事对象

     */

    private void opeCDDriverReadData(CDDriver cd){

       //1:先获取光驱读取的数据

       String data = cd.getData();

       //2:把这些数据传递给CPU进行处理

       this.cpu.executeData(data);

    }

    /**

     * 处理CPU处理完数据后与其它对象的交互

     * @param cpu CPU同事类

     */

    private void opeCPU(CPU cpu){

       //1:先获取CPU处理过后的数据

       String videoData = cpu.getVideoData();

       String soundData = cpu.getSoundData();

       //2:把这些数据传递给显卡和声卡展示出来

       this.videoCard.showData(videoData);

       this.soundCard.soundData(soundData);

    }

}

(5)看个电影享受一下

       定义完了同事类,也实现处理了它们交互的中介者对象,该来写个客户端使用它们,来看个电影,好好享受一下。写个客户端测试一下,看看效果,示例代码如下:

public class Client {

    public static void main(String[] args) {

       //1:创建中介者——主板对象

       MotherBoard mediator = new MotherBoard();

       //2:创建同事类

       CDDriver cd = new CDDriver(mediator);

       CPU cpu = new CPU(mediator);

       VideoCard vc = new VideoCard(mediator);

       SoundCard sc = new SoundCard(mediator);

 

       //3:让中介者知道所有的同事

       mediator.setCdDriver(cd);

       mediator.setCpu(cpu);

       mediator.setVideoCard(vc);

       mediator.setSoundCard(sc);

 

       //4:开始看电影,把光盘放入光驱,光驱开始读盘

       cd.readCD();

    }

}

测试结果如下:

您正观看的是:设计模式

画外音:值得好好研究

如同上面的示例,对于光驱对象、CPU对象、显卡对象和声卡对象,需要相互交互,虽然只是简单演示,但是也能看出来,它们的交互是比较麻烦的,于是定义一个中介者对象——主板对象,来维护它们之间的交互关系,从而使得这些对象松散耦合。

如果这个时候需要修改它们的交互关系,直接到中介者里面修改就好了,也就是说它们的关系已经独立封装到中介者对象里面了,可以独立的改变它们之间的交互关系,而不用去修改这些同事对象。

 

未完待续

4
5
分享到:
评论

相关推荐

    设计模式之中介者模式(Mediator)

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

    设计模式之中介者模式(Mediator Pattern)

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

    研磨设计模式(完整带书签).part2.pdf

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template ...

    研磨设计模式(完整带书签).part1.pdf

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template ...

    中介者模式(Mediator Pattern)原理图

    中介者模式(Mediator Pattern)是一种行为型设计模式,用于减少对象之间的直接相互依赖,使得对象间的交互通过一个中介者对象来进行协调。在中介者模式中,对象之间不再直接相互调用,而是通过中介者对象来传递消息...

    设计模式 Mediator 中介者 c++

    中介者模式的完整代码。 程序默认使用vs开发。其他开发工具可能需要做少许调整。

    Java设计模式之中介者模式(Mediator Pattern)简介

    主要介绍了Java设计模式之中介者模式(Mediator Pattern),需要的朋友可以参考下

    PHP设计模式之中介者模式(Mediator Pattern)入门与应用案例详解

    咱们先来看下中介者模式(Mediator Pattern)的定义,它就是,用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互,这种模式又称为调停...

    (行为型模式) Mediator 中介者模式

    C#面向对象设计模式 (行为型模式) Mediator 中介者模式 视频讲座下载

    研磨设计模式-part2

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template ...

    javascript设计模式之中介者模式Mediator

    主要介绍了javascript设计模式之中介者模式Mediator,需要的朋友可以参考下

    研磨设计模式.part2(共4个)

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式...

    研磨设计模式-part4

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template ...

    研磨设计模式-part3

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template ...

    C++设计模式课件17_Mediator_中介者.pdf

    C++设计模式课件17_Mediator_中介者.pdf

    JAVA设计模式chm文档

    创建模式: 设计模式之Factory 设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) 结构模式: ...设计模式之Mediator(中介者) 设计模式之Interpreter(解释器) 设计模式之Visitor

    研磨设计模式.part3(共4个)

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式...

    研磨设计模式.part4(共4个)

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式...

    研磨设计模式.part1(共4个)

    第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式...

Global site tag (gtag.js) - Google Analytics