概述

中介者模式是用来降低多个对象和类之间的通信复杂性,这种模式提供一个中介者用来处理多个对象和类之间复杂的依赖关系,所有的依赖关系都通过中介者来处理,降低了对象间的耦合,中介者模式属于行为型模式。

process中介变量是二分类应该用模型 process中介模型图_设计模式

如图所示,左侧是一个对象依赖的关系图,多个对象之间相互依赖,形成一个复杂的网状图,这样会导致整个逻辑错综复杂,理解起来比较费劲而且不容易扩展。在右侧我们引入中介者,所有的对象依赖全部通过中介者来完成,整个结构清晰不少,也减少了对象间的耦合,利于扩展。

类图

process中介变量是二分类应该用模型 process中介模型图_中介者_02

以聊天室的例子来说明中介者模式,一般中介者包括4种角色

  • 抽象中介者(AbstractChatRoom):是中介者的抽象定义
  • 实际中介者(WechatRoom):抽象中介者的具体实现者
  • 抽象同事对象(AbstractUser):对象的抽象定义
  • 具体同事对象(NewUser、OldUser):对象功能的具体实现者

实现代码

public abstract class AbstractUser {

    protected AbstractChatRoom chatRoom;

    public abstract void send(String msg);
    public abstract void receive(String msg);

    public void setChatRoom(AbstractChatRoom chatRoom){
        this.chatRoom = chatRoom;
    }
}



public class NewUser extends AbstractUser {
    @Override
    public void send(String msg) {
        System.out.println("NewUser send msg:" + msg);
        //通过中介者调用接收消息
        this.chatRoom.receive(this,msg);
    }

    @Override
    public void receive(String msg) {
        System.out.println("NewUser receive msg:" + msg);
    }
}


public class OldUser extends AbstractUser {
    @Override
    public void send(String msg) {
        System.out.println("oldUser send msg:" + msg);
        //通过中介者调用接收消息
        this.chatRoom.receive(this,msg);
    }

    @Override
    public void receive(String msg) {
        System.out.println("OldUser receive msg:" + msg);
    }
}



public abstract class AbstractChatRoom {

    protected abstract void login(AbstractUser user);

    protected abstract void receive(AbstractUser user,String msg);

}

public class WechatRoom extends AbstractChatRoom {

    private List<AbstractUser> userList;

    public WechatRoom(){
        this.userList = new ArrayList<AbstractUser>();
    }

    //用户登录
    @Override
    public void login(AbstractUser user){
        if(!userList.contains(user)){
            userList.add(user);
        }
    }

    //接收消息
    @Override
    protected void receive(AbstractUser user,String msg) {
        userList.forEach(u -> {
            if(!u.equals(user)){
                u.receive(msg);
            }
        });
    }

}

public class Client {
    public static void main(String[] args){
        //创建聊天室(中介者)
        AbstractChatRoom chatRoom = new WechatRoom();
        //创建用户(具体对象)
        AbstractUser oldUser = new OldUser();
        AbstractUser newUser = new NewUser();

        //登录(用户注册到聊天室)
        chatRoom.login(oldUser);
        chatRoom.login(newUser);
        //用户绑定聊天室
        oldUser.setChatRoom(chatRoom);
        newUser.setChatRoom(chatRoom);
        //用户发送消息
        newUser.send("hello I'm newUser");
        oldUser.send("hello I'm oldUser");
    }
}

输出结果:
NewUser send msg:hello I'm newUser
OldUser receive msg:hello I'm newUser
oldUser send msg:hello I'm oldUser
NewUser receive msg:hello I'm oldUser

优缺点

优点

中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合

缺点

中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。

使用场景

  • 机场调度中心

每个机场都有一个调度中心,用来做飞机起飞、降落等的协调调度,调度中心就相当于中介者,所有的飞机都需要跟调度中心交互,这样整个机场的运行才能有条不紊

  • MVC框架

MVC是很流利的框架,C即Controller在这里就是中介者的角色,用来协调Model和View的功能

  • 媒体网关

网关也是中介都的角色,网络上任意两个角色的通信,都要先通过网关的转发

  • 中介服务

在软件设计场景,一般如下场景建议使用中介者模式:

  • 多个对象相互之间依赖,并且以后有发生改变的可能
  • 产品开发。例如类似MVC模式通用的框架,需要考虑通用性和扩展性,可以考虑引入中介者模式

注意事项

中介者是一个很好的封装模式,也是一个容易被滥用的模式,在实现开发过程中几个对象相互之间依赖是很正常的事情,纯粹的理论家会要求这种时候使用中介者模式来进行封装,这是不可取的,中介者模式会使大量的依赖集中在中介者身上,这是不恰当的,要根据实际情况来决定是否要引入中介者

总结一下

  • 中介者模式是用来降低多个对象和类之间的通信复杂性
  • 中介者用来处理多个对象和类之间复杂的依赖关系,所有的依赖关系都通过中介者来处理,降低了对象间的耦合
  • 中介者一般包括4种角色
  • 抽象中介者(AbstractChatRoom):是中介者的抽象定义
  • 实际中介者(WechatRoom):抽象中介者的具体实现者
  • 抽象同事对象(AbstractUser):对象的抽象定义
  • 具体同事对象(NewUser、OldUser):对象功能的具体实现者
  • 优点:中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合
  • 缺点:中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。
  • 使用场景
  • 机场调度中心
  • MVC框架
  • 媒体网关
  • 中介服务
  • 注意事项:中介者是一个很好的封装模式,也是一个容易被滥用的模式,在实现开发过程中几个对象相互之间依赖是很正常的事情,纯粹的理论家会要求这种时候使用中介者模式来进行封装,这是不可取的,中介者模式会使大量的依赖集中在中介者身上,这是不恰当的,要根据实际情况来决定是否要引入中介者