行为模式之中介者模式

Posted by Night Field's Blog on May 29, 2020

1 概述

中介者模式(Mediator Pattern)是一种行为模式,通过定义一个中介对象,来管理一系列对象之间的依赖,从而解耦原有对象之间的关系。

2 中介者模式

大量的对象相互依赖,会大大增加系统复杂度,提高维护成本。中介者模式(Mediator Pattern)是迪米特原则的一个很好体现,它通过将对象的依赖关系维护在一个中介者中,使原本耦合在一起的对象变得相互独立。 交通信号灯是一个很常见的例子,如果没有信号灯,十字路口的车子必须知道互相之间要去的方向,来决定什么时候踩油门,什么时候踩刹车,如此一来很容易堵车。而信号灯的作用就是中介者,司机们不用关心其他车子,只需按照“红灯停,绿灯行”的规则,按照灯的指示来做行驶。信号灯充当来中介者,维护了交通秩序。

3 案例

让我们来看一个更简单的例子。聊天室提供了群聊的功能,可以增加,删除成员。内部的人员,可以将消息发送给所有的其他人。如果说每个成员内部都维护一个所有成员的列表,直接点对点发送消息,那么当人数很多的时候,整个逻辑会变得很复杂,同时,对于人员的增减,也将是个繁重的工作。现实中我们当然不会这么做,而是通过定义一个ChatRoom对象,来维护群聊成员列表,同时负责管理消息的发送,看看用中介者模式,如何优雅地设计聊天室:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public interface ChatRoom {
    void broadcast(String message, Member sender);
    void addMember(Member member);
    void removeMember(Member member);
}
public class ChatRoomImpl implements ChatRoom {
    List<Member> memberList = new ArrayList<>();
    @Override
    public void broadcast(String message, Member sender) {
        for (Member member : memberList) {
            if (!member.equals(sender)) {
                member.receive(message);
            }
        }
    }
    @Override
    public void addMember(Member member) {
        if (!memberList.contains(member)) {
            memberList.add(member);
            member.setChatRoom(this);
        }
    }
    @Override
    public void removeMember(Member member) {
        memberList.remove(member);
    }
}

public abstract class Member {
    protected ChatRoom chatRoom;
    protected String name;
    public Member(String name){
        this.name=name;
    }
    public void setChatRoom(ChatRoom chatRoom) {
        this.chatRoom = chatRoom;
    }
    public abstract void send(String message);
    public abstract void receive(String message);
}
public class MemberImpl extends Member {
    public MemberImpl(String name) {
        super(name);
    }
    @Override
    public void send(String message) {
        System.out.println(name + " send message: " + message);
        chatRoom.broadcast(message, this);
    }
    @Override
    public void receive(String message) {
        System.out.println(name + " received message: " + message);
    }
}

public class Test {
    public static void main(String[] args) {
        ChatRoom chatRoom = new ChatRoomImpl();
        Member link = new MemberImpl("Link");
        Member mario = new MemberImpl("Mario");
        Member yoshi = new MemberImpl("Yoshi");

        chatRoom.addMember(link);
        chatRoom.addMember(mario);
        chatRoom.addMember(yoshi);

        link.send("Hello");
    }
}

输出:

1
2
3
Link send message: Hello
Mario received message: Hello
Yoshi received message: Hello

可以发现,Member对象之间,无需彼此依赖,甚至都不需要知道彼此之间的存在,所有的关系依赖都维护在ChatRoom中。对于成员的修改,增减,并不会影响到整个系统。 其实即时通信类的架构模式,都是上述模式的扩展。比如微信中,每个客户端(IOS/Android)充当的是Member角色,他们之间并不直接交互,而是通过腾讯的服务器(ChatRoom角色),来发送和接收消息。从某种意义上来说,中介者模式是即时通信的基石。

4 总结

中介者模式使得程序更易于修改和扩展。当对象之间的关系/通信很复杂的时候,可以看看,是否可以通过抽象出一个中心点作为中介者,来解耦了对象之间的依赖。

文中例子的github地址