设计模式(21)行为型模式 - 中介者模式

前言

温故而知新

先复习前面学到的行为型模式:

  • 模板方法模式:定义一个算法、流程骨架,将特定步骤的实现延迟到子类,完成模板的复用(请客流程:点单 -》吃 -》买单,具体吃什么可以由子类决定)
  • 命令模式:将命令封装成对象,聚合执行者,使请求者仅需使用命令对象即可完成命令,执行者与请求者完全解耦合(遥控器上的按钮就是一个个命令对象,遥控器仅需按下按钮即可完成开关灯命令)
  • 访问者模式:将施加于对象结构的元素上的操作隔离,封装成访问者,对象结构提供访问者访问的接口,即修改访问者不会影响到对象结构(购物车就是一个对象结构,上面的各个商品是各种元素对象,顾客访问者可以查看质量,收银员可以查看价格)
  • 迭代器模式:将聚合对象中数据对象的存储与遍历功能分隔,遍历功能封装成迭代器,聚合对象工厂方法创建相对应的迭代器(Linux目录用迭代器描述目录结构)
  • 观察者模式:定义对象间的一对多的依赖关系,当对象状态改变时,会自动通知所有依赖的对象并自动更新对象数据(气象局天气数据改变,各网站天气数据也改变)

接下来,学习中介者模式


现实中的问题

设计模式(21)行为型模式 - 中介者模式_第1张图片
现实中,对象间的交互关系一般是网状结构,每个对象都必须知道它需要交互的对象,例如,你电话号换了,需要通知父母、亲人、同学自己电话换了,对应如果软件也是这样的,就会十分的复杂

设计模式(21)行为型模式 - 中介者模式_第2张图片
例如QQ聊天,如果真的要你的电脑与聊天对象的电脑连接,需要知道IP地址,聊天对象也需要知道我们的地址才能发信息给我们
如果这样就太复杂了,现实是我们是发送消息给QQ的服务器,QQ服务器再找到我们的聊天对象的IP地址,把消息发送过去

服务器就是一个中介者,它把对象间的网状关系变成了星形结构

设计模式(21)行为型模式 - 中介者模式_第3张图片


中介模式

什么是中介者模式?

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

为什么要中介者模式?

在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责

对于一个模块,可能由很多对象构成,而且这些对象之间可能存在相互的引用,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式

模式结构

设计模式(21)行为型模式 - 中介者模式_第4张图片

模式角色:

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法
  • 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个集合来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互

模式实现案例

简单描述一下QQ群聊的过程

小明发送信息,小红能够收到

设计模式(21)行为型模式 - 中介者模式_第5张图片

package com.company.Behavioral.Mediator;

import java.util.ArrayList;
import java.util.List;
//抽象中介者
abstract class Mediator {
    public abstract void register(Colleague colleague);
    public abstract void forward(Colleague colleague);
}
//具体中介者
class QQServer extends Mediator{
    private List<Colleague> colleaguelist;

    public QQServer() {
        this.colleaguelist = new ArrayList<Colleague>();
    }

    @Override
    public void register(Colleague colleague) {
        colleaguelist.add(colleague);
        //注册时,把中介者聚合到同事类
        colleague.setMediator(this);
    }

    @Override
    public void forward(Colleague colleague) {
        for (Colleague colleague1 : colleaguelist){
            //转发给除自己外的注册在服务器上的人
            if (!colleague.equals(colleague1)){
                colleague1.receive();
            }
        }
    }
}
//抽象同事类
abstract class Colleague{
    protected Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void receive();
    public abstract void send();
}
//具体同事类小明
class XiaoMing extends Colleague{
    @Override
    public void receive() {
        System.out.println("====小明接收到了信息====");
    }

    @Override
    public void send() {
        System.out.println("====小明发送信息====");
        mediator.forward(this);
    }
}
//具体同事类:小红
class XiaoHong extends Colleague{
    @Override
    public void receive() {
        System.out.println("====小红接收到了信息====");
    }

    @Override
    public void send() {
        System.out.println("====小红发送信息====");
        mediator.forward(this);
    }
}

class Test{
    public static void main(String[] args) {
        //创建具体同事类
        Colleague xiaoHong = new XiaoHong();
        Colleague xiaoMing = new XiaoMing();
        //创建中介者
        Mediator qqServer = new QQServer();
        //注册
        qqServer.register(xiaoHong);
        qqServer.register(xiaoMing);
        //小明发送信息
        xiaoMing.send();
        
    }
}

设计模式(21)行为型模式 - 中介者模式_第6张图片

这里QQ服务器类转发功能只是简单处理了一下


模式分析

  • 中介模式将对象间复杂的网状结构关系改变成了星型结构关系

设计模式(21)行为型模式 - 中介者模式_第7张图片

  • 中介者承担了两个职责:

中转作用(结构性):通过中介者提供的中转作用,各个同事对象就不再需要显式引用其他同事,当需要和其他同事进行通信时,通过中介者即可。该中转作用属于中介者在结构上的支持

协调作用(行为性):中介者可以更进一步的对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对同事的请求进行进一步处理,将同事成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持


模式优缺点

优点

  • 简化了对象之间的交互
  • 将各同事解耦
  • 减少子类生成
  • 可以简化各同事类的设计和实现

缺点

解耦合一般付出的代价就是系统复杂度的提高

在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护

中介者模式类似与把同事类间的耦合全部集中在中介者上,导致中介者的复杂度提高


适用环境

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解
  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象
  • 通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的中介者类

模式扩展

  1. 应用

中介者模式使用也较多

MVC模式是Java EE 的一个基本模式,此时控制器Controller作为一种中介者,它负责控制视图对象View和模型对象Model之间的交互

  1. 简化

不定义抽象中介者,使用单例模式具体中介者(一个关系中,中介者一般是只有一个的)

同事对象不持有中介者,而是在需要的时直接获取中介者对象并调用(配合单例模式)

  1. 迪米特法则

迪米特法则:限制软件实体之间通信的宽度和深度

中介者模式将同事类间的关联关系减少,符合迪米特法则


总结

  • 中介者模式是用一个中介对象封装对象间的一系列的交互,消除对象间的显示引用,松散耦合
  • 中介者模式有4个角色:抽象中介者、具体中介者、抽象同事类、具体同事类
  • 抽象中介者定义与各个同事对象间的通信;具体中介者协调各个同事类实现协作行为,维护对各个同事对象的引用;抽象同事类定义对中介者的通信方法;具体同事类实现与中介者的通信间接完成与其他同事类的通信
  • 中介者模式优点:简化了对象间的交互,简化了同事类的设计与实现;缺点:具体中介类复杂,难以维护
  • 中介者将系统的网状结构变成了星型结构,中介者承担了中转作用和协调作用
  • 中介者模式适用于:对象间存在复杂的引用关系、相互依赖关系;想通过一个中间类封装多个类的行为
  • 中介者模式实际使用一般都是不使用抽象中介者,具体中介者使用单例模式,同事类不聚合中介者,仅使用时调用中介者方法

你可能感兴趣的:(Java+设计模式)