设计模式之 中介者模式

中介者模式(Mediator Design Pattern),是通过一个中介对象,来封装多个对象之间的交互,将原本直接沟通的A和B,变为A<–>中介者<–>B。

比如我们现在用的微信聊天,张三的微信账号,有30个好友,他的每个好友也各自有30各好友,并且好友之间也有重叠。如果微信的设计是点对点发送消息,点对点也就是张三和他的好友A发消息,是直接从张三手机将消息发给A的手机,那么张三如果同时和他的30个好友聊天,并且他的30个好友也同时和各自的30个好友聊天,这将组成一个庞大的网,关系错综复杂。

有没有一种方法,让这种复杂的场景变得简单呢?

那就是我们本节的主角中介者模式了。

中介者模式就是作为消息的中转者,不管是谁,发消息,都是发到中介者,由中介者转发,这样就从一种网状关系,变成了星状结构,中介者在模式中就是星状结构的中心。

我们先来演示一个简单的例子,三个用户A、B、C一起聊天,A、B、C都是讲消息发送给中介者,通过中介者将消息广播出来。

1、新建中介者类

package com.itzhimei.study.design.mediator;

/**
 * www.itzhimei.com
 * 中介者
 */
public class Mediator {

    public static void showMessage(User user,String message) {
        System.out.println("用户"+user.getName()+":"+message);
    }
}

2、新建用户类

package com.itzhimei.study.design.mediator;

/**
 * www.itzhimei.com
 * 用户
 */
public class User {

    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sendMessage(String message) {
        Mediator.showMessage(this, message);
    }

}

3、测试

package com.itzhimei.study.design.mediator;

public class Client {

    public static void main(String[] args) {
        User a = new User("A");
        User b = new User("B");
        User c = new User("C");

        a.sendMessage("大家好,我是A");
    }
}

输出结果:

用户:A:大家好,我是A

通过中介者,三个用户A、B、C之间就实现了解耦。

类关系图:

上面的demo有点简单,中介者发消息的动作不那么形象,我们再对上面的代码进行一点改造。

1、定义中介者接口

package com.itzhimei.study.design.mediator.mda;

/**
 * www.itzhimei.com
 * 中介者接口
 */
public interface IMediator {

    /**
     * 注册用户
     */
    void regist(IUser user);

    /**
     * 中转消息给其他用户
     * @param user
     */
    void notifyAllMessage(IUser user);
}

2、定义中介者实体

package com.itzhimei.study.design.mediator.mda;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * www.itzhimei.com
 * 中介者:定义职责  1、注册持有用户  2、转发消息
 */
public class Mediator implements IMediator {

    private List<IUser> userList = new ArrayList<>();

    @Override
    public void regist(IUser user) {
        if(user != null && !userList.contains(user)) {
            userList.add(user);
        }
    }

    @Override
    public void notifyAllMessage(IUser user) {
        if(!userList.isEmpty()) {
            Iterator<IUser> iterable = userList.iterator();
            while(iterable.hasNext()) {
                IUser u = iterable.next();
                if(u != null && !u.equals(user)) {
                    u.receiveMessage(user.getMessage());
                }
            }
        }
    }
}

中介者中有两个方法,1、注册持有用户 2、转发消息

3、定义用户接口

package com.itzhimei.study.design.mediator.mda;

public interface IUser {

    void receiveMessage(String message);

    void sendMessage(String message);

    String getMessage();
}

4、定义抽象用户,实现用户通用行为,定义用户通用属性

package com.itzhimei.study.design.mediator.mda;

/**
 * www.itzhimei.com
 * 用户抽象类:持有中介者
 */
public abstract class AbstractUser implements IUser {

    private IMediator mediator;

    private String name;

    private String message;

    public AbstractUser(IMediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public void sendMessage(String message) {
        this.message = message;
        mediator.notifyAllMessage(this);
    }

    public IMediator getMediator() {
        return mediator;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

在这其中,就持有了中介者,用于用户注册到中介者,并用中介者发送信息。

5、测试

package com.itzhimei.study.design.mediator.mda;

/**
 * www.itzhimei.com
 * 测试
 */
public class Client {

    public static void main(String[] args) {
        IMediator m = new Mediator();
        IUser a = new User(m,"A");
        IUser b = new User(m,"B");
        IUser c = new User(m,"C");
        //发送消息
        a.sendMessage("hello world");
    }
}

测试输出:

用户B收到:hello world
用户C收到:hello world

用户A发送的消息,B和C都收到了,最终达到了用户之间的解耦。

这就是中介者的作用。

类关系图:

中介者模式中包含的角色:

抽象中介者:定义中介者的职责,之所以有抽象中介者,其实就是遵循设计模式的依赖倒置原则。

具体中介者:实现中介者的具体实现类,职责包括注册用户、转发消息。

抽象用户:定义用户行为和属性。

具体用户:实际用户,发送和接收消息。

总结:

中介者模式是使用一个中间角色来处理多个角色之间的关系,比如通信关系,通过中介自身来解耦多个角色,让系统角色的整体关系更加简单。