中介者模式(Mediator)

145 阅读3分钟

定义

用一个中介对象来封装一系列的对象交互,使得各系统对象不需要显示的相互调用,从而使其耦合松散并且可以独立的改变他们的之间的交互。

本质

封装交互

登场角色

  • Mediator(仲裁者、中介者)

    Mediator角色负责定义与Colleague角色进行通信和做出决定的接口。

  • ConcreteMediator(具体的仲裁者、中介者)

    实现了Mediator角色的接口,负责实际做出决定。

  • Colleague(同事)

    负责定义与Mediator角色进行通信的接口。

  • ConcreteColleague(具体的同事)

    负责实现Colleague角色的接口。

示例代码

public abstract class Mediator {
    abstract void change(Colleague c);
}

public class MainBoard extends Mediator{
    private CDDevice cdDevice;//光驱设备
    private CPU cpu;//CPU
    private SoundCard soundCard;//声卡设备
    private GraphicsCard graphicsCard;//显示设备


    @Override
    void change(Colleague c) {
        if(c == cdDevice){
            handlerCD((CDDevice)c);
        }else if(c == cpu){
            handleCPU((CPU)c);
        }
    }

    private void handlerCD(CDDevice cdDevice){
        cpu.decodeData(cdDevice.getDataVideo());
    }

    private void handleCPU(CPU cpu){
        soundCard.soundPlay(cpu.getDataSound());
        graphicsCard.videoPlay(cpu.getDataVideo());
    }

    public void setCdDevice(CDDevice cdDevice) {
        this.cdDevice = cdDevice;
    }

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public void setSoundCard(SoundCard soundCard) {
        this.soundCard = soundCard;
    }

    public void setGraphicsCard(GraphicsCard graphicsCard) {
        this.graphicsCard = graphicsCard;
    }
}

public abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
}


public class CPU extends Colleague{
    String dataVideo,dataSound;//视频数据和音频数据
    public CPU(Mediator mediator) {
        super(mediator);
    }

    public String getDataVideo() {
        return dataVideo;
    }

    public void setDataVideo(String dataVideo) {
        this.dataVideo = dataVideo;
    }

    public String getDataSound() {
        return dataSound;
    }

    public void setDataSound(String dataSound) {
        this.dataSound = dataSound;
    }
    public void decodeData(String data){
        System.out.println("CPU解码音频和视频数据");
        //通知中介者数据改变
        System.out.println("通知中介者自身状态改变");
        mediator.change(this);
    }
}



public class CDDevice extends Colleague{
    String dataVideo;//视频数据
    public CDDevice(Mediator mediator) {
        super(mediator);
    }

    public String getDataVideo() {
        return dataVideo;
    }
    public void load(){
        dataVideo = "从视频流中加载视频数据";
        mediator.change(this);
    }
}



public class GraphicsCard extends Colleague{
    public GraphicsCard(Mediator mediator) {
        super(mediator);
    }

    /**
     * 播放视频
     * @param data
     */
    public void videoPlay(String data){
        System.out.println("播放视频");
    }
}
public class SoundCard extends Colleague{
    public SoundCard(Mediator mediator) {
        super(mediator);
    }

    /**
     * 播放音频
     * @param data
     */
    public void soundPlay(String data){
        System.out.println("播放音频");
    }
}

public class Client {
    public static void main(String[] args){
        //构造主板对象
        MainBoard mediator = new MainBoard();
        //分别构造各个零部件
        CDDevice cdDevice = new CDDevice(mediator);
        CPU cpu = new CPU(mediator);
        GraphicsCard graphicsCard = new GraphicsCard(mediator);
        SoundCard soundCard = new SoundCard(mediator);
        ///将各个零部件安装到主板
        mediator.setCdDevice(cdDevice);
        mediator.setCpu(cpu);
        mediator.setGraphicsCard(graphicsCard);
        mediator.setSoundCard(soundCard);
        //播放视频
        cdDevice.load();

    }
}

运行结果

CPU解码音频和视频数据
通知中介者自身状态改变
播放音频
播放视频

功能

封装对象之间的交互。如果一个对象的操作会引起其他对象的变化,或者是某个操作需要引起其他对象的变化,而这个对象又不想自己来处理这些关系,就可以借由中介者模式实现。

优点

  • 松散耦合

    把多个对象同事之间的交互封装到中介者对象里面,使得同事对象松散耦合,基本可以做到互不依赖。

  • 集中控制交互

    多个同事对象之间的交互,被封装到中介者对象中集中管理,使得这些交互行为改变时,只变更中介者对象即可。

  • 多对多变成一对多

缺点

  • 存在的一个潜在的缺点是过度集中化。

使用场景

  • 如果一组对象之间的通信方式比较复杂,导致互相依赖、结构混乱,可以采用中介者模式。
  • 如果一个对象引用很多对象,并直接跟这些对象交互,导致难以复用该对象,可以采用中介者模式。