中介模式(MediatorPattern),属于行为型设计模式。目的是把系统中对象之间的调用关系从一对多转变成一对一的调用关系,以此来降低多个对象和类之间的通信复杂性。
在很多情况下,一个类中对象于对象之间的调用往往很容易形成网状结构,此时倘若一个对象发生改变,那么将会导致其他所有与之关联的对象进行修改,从而导致系统复杂性增加,且难以维护。
使用中介模式,可以通过向系统中引入中介类,将这种网状结构改为星型结构,各个对象直接不直接关联而是通过该中介类进行交互,当一个对象发生改变时,只需要在中介类中做出相应的修改即可,其他对象对此变化是无感的。
用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
使用下面图示可能会更好的进行表达
在我们日常生活中,处处存在中介模式的影子。
房产中介
有了房产中介,我们只需要联系中介小哥就行了,中介小哥有各个房东的钥匙,直接看房,十分方便。
线上招聘平台
有了线上招聘平台后,应聘者直接在平台上联系各个公司就好了,通过该平台,应聘者不仅可以看到各种大中小公司,还不会因为公司招聘流程的改变而受影响,因为应聘者在平台上的操作都是一样的。
在中介模式中,最重要的角色就是**中介角色(Mediator)**了,它用于在系统中各个对象之间建立关联关系。
抽象中介接口类(Mediator)
定义中介的功能。
具体中介类(MediatorImpl)
实现中介接口类定义的功能。在实现的功能逻辑中,给各个对象建立关联关系,因此中介类中需要维护一个包含关联的各个组件的集合并对该集合进行维护。
系统组件抽象接口类(Component)
定义系统中各个对象的功能。
系统组件具体实现类(AComponent、BComponent、CComponent)
实现各个对象的功能。
通过对中介模式中各个角色的分析,可得其通用UM图如下所示
以群发消息为例,每当我们在重大传统节日时,许多人喜欢使用短信群发的形式,将节日祝福一次性群发给他的亲朋好友们。这是一个非常好的案例,在没有群发功能的时候,我们想好一段祝福语后,需要一个接一个地对通讯录中的朋友进行发送短信(一对多);而后来有了群发功能后,我们选择群发功能,将亲朋好友都添加到这个功能中作为群发联系人,然后点击发送短信就可以将祝福发送给所有人了(一对一)。此时群发功能就相当于中介。
1.角色分析
联系人接口(Friend)
定义联系人的功能。在节日祝福中,我们通讯录中的联系人有个接收短信功能receiveMessage()就够了。
publicinterfaceFriend{voidreceiveMessage(Stringmessage);}具体联系人(FriendImpl)
实现联系人接口(Friend)定义的功能。假设联系人有三个:父亲、母亲、姐姐。
publicclassFatherimplementsFriend{@OverridepublicvoidreceiveMessage(Stringmessage){System.out.println("父亲收到短信:"+message);}}publicclassMotherimplementsFriend{@OverridepublicvoidreceiveMessage(Stringmessage){System.out.println("母亲收到短信:"+message);}}publicclassSisterimplementsFriend{@OverridepublicvoidreceiveMessage(Stringmessage){System.out.println("姐姐收到短信:"+message);}}抽象群发接口(SendGroup)
定义一个发送功能send(),以及对群发目标联系人的维护功能addFriend()、removeFriend()。
publicinterfaceSendGroup{voidaddFriend(Friendfriend);voidremoveFriend(Friendfriend);voidsend(Stringmessage);}具体群发中介类(SendGroupImpl)
实现抽象群发接口SendGroup定义的功能。前面分析中说过,中介类中需要维护一个包含所有联系人的集合并对其进行维护。
publicclassSendGroupImplimplementsSendGroup{privatefinalList
新建一个客户端类对该案例进行演示
publicclassMediatorClient{publicstaticvoidmain(String[]args){Friendfather=newFather();Friendmother=newMother();Friendsister=newSister();//选择需要群发短信的联系人SendGroupsendGroup=newSendGroupImpl();sendGroup.addFriend(father);sendGroup.addFriend(mother);sendGroup.addFriend(sister);//群发短信sendGroup.send("新年快乐");}}运行该代码后得到以下输出
优点:
缺点:
对客户端的代码维护,转变为对中介类的维护,中介类变得庞大时也将同样难以维护。