【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。

什么是中介者模式(Mediator)

概念

中介者模式(Mediator Pattern)属于行为型模式,中介者模式是为了解决对象之间相互引用的情况,通过中介者对象来解除这些对象之间的相互引用,让对象之间的通信交给中介者对象来完成,使得对象从网状结构转变成了星形结构,以此降低对象间的耦合程度。

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第1张图片

像我们在水群里聊天,我们可以把每个客户端当成一个对象,如果采用网状结构,那么就得每个客户端都得记录其他客户端的地址才行,那一个人想要加入这个水群就非常地困难,如果是采用星形结构,每个客户端都和一个服务端进行连接,服务端可以看作一个中介者,所有的客户端想要收发消息都得通过服务端,服务端会帮客户端转发消息,这样每个客户端想要加入水群,只需要找到这个服务端即可,这样就特别方便了。

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第2张图片

优点

  1. 符合迪米特法则,单一职责原则。由中介者来完成和其他对象的交互,对象无需知道和其他对象交互的过程。
  2. 减低了类的复杂程度。将对象一对多的关系装换成了一对一的关系,也有利于系统的维护和扩展。

总之就是减少了对象之间的交集。

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第3张图片

缺点

  1. 当中介者承担越来越多的责任时,会使系统变得复杂难以维护。

这也是无可厚非的,可以考虑新建其他类来降低中介者的责任。

原则

“+”代表遵守,“-”代表不遵守或者不相关

原则 开放封闭 单一职责 迪米特 里氏替换 依赖倒置 接口隔离 合成复用
- + + - + - -

适用场景

  1. 对象之间呈现网状结构
  2. 想要通过一个类来封装多个对象的行为。

如何实现

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第4张图片

想要实现中介者模式,需要以下四个对象:

  1. 中介者抽象类/接口:定义同事对象注册与转发信息的操作。
  2. 中介者实现类:实现中介者抽象类/接口,定义一个集合来管理同事对象。
  3. 同事抽象类:定义同事类的方法,依赖中介者对象。
  4. 同事类:实现同事抽象类,当需要和其他同事对象交互时,调用中介者对象。

类图

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第5张图片

同事对象中需要包含中介者,中介者中包含所有同事对象。

例子

就照着上面水群的例子吧,写一个模拟群聊的代码。

类图

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第6张图片

代码

中介者接口

/**
 * Created on 2021/6/11.
 *
 * @author xuxiaobai
 */
public interface Server {


    /**
     * 注册客户端
     * @param client
     */
    void register(Client client);

    /**
     * 服务端帮忙转发
     * @param message
     * @param source
     */
    void relay(String message,Client source);

    /**
     * 注销客户端
     * @param client
     */
    void cancel(Client client);
}

中介者实现类

/**
 * 中介者
 * 服务端
 * Created on 2021/6/11.
 *
 * @author xuxiaobai
 */
public class ChatServer implements Server{
    List<Client> clients=new ArrayList();


    @Override
    public void register(Client client) {
        clients.add(client);
    }

    @Override
    public void relay(String message,Client source) {
        System.out.println("<接收情况");
        clients.forEach((item)->{
            if (source.equals(item)){
                return;
            }
            item.receiver(message);
        });
        System.out.println("接收情况>");
    }

    @Override
    public void cancel(Client client) {
        clients.remove(client);
    }
}

同事抽象类

/**
 * Created on 2021/6/11.
 *
 * @author xuxiaobai
 */
public abstract class Client {
    protected Server server;

    protected String username;

    public Client(Server server,String username){
        this.server=server;
        this.username=username;
    }

    /**
     * 修改服务器
     * @param server
     */
    public abstract void changeServer(Server server);


    /**
     * 接收消息
     * @param msg
     */
    public abstract void receiver(String msg);


    /**
     * 发送消息
     * @param msg
     */
    public abstract void send(String msg);

}

同事实现类

/**
 * 同事类
 * 客户端
 * Created on 2021/6/11.
 *
 * @author xuxiaobai
 */
public class ChatClient extends Client{



    public ChatClient(Server server, String username) {
        super(server, username);
        server.register(this);
    }

    public void changeServer(Server server){
        super.server.cancel(this);
        super.server=server;
        server.register(this);
    }

    @Override
    public void receiver(String msg) {
        System.out.println(username+"接收到了消息:"+msg);
    }

    @Override
    public void send(String msg) {
        System.out.println(username+"发送消息:"+msg);
        server.relay(this.username+"说"+msg,this);
    }
}

测试类

/**
 * 测试类
 * Created on 2021/6/11.
 *
 * @author xuxiaobai
 */
public class MediatorTest {
    public static void main(String[] args) {
        Server server=new ChatServer();
        //模拟客户端,加入服务器
        Client clientA=new ChatClient(server,"ClientA");
        Client clientB=new ChatClient(server,"ClientB");
        Client clientC=new ChatClient(server,"ClientC");

        //模拟通话
        clientA.send("hi");
        clientB.send("hello");
        clientA.send("我们说中文吧。");
        clientB.send("好。");
        /**
         * ClientA发送消息:hi
         * <接收情况
         * ClientB接收到了消息:ClientA说hi
         * ClientC接收到了消息:ClientA说hi
         * 接收情况>
         * ClientB发送消息:hello
         * <接收情况
         * ClientA接收到了消息:ClientB说hello
         * ClientC接收到了消息:ClientB说hello
         * 接收情况>
         * ClientA发送消息:我们说中文吧。
         * <接收情况
         * ClientB接收到了消息:ClientA说我们说中文吧。
         * ClientC接收到了消息:ClientA说我们说中文吧。
         * 接收情况>
         * ClientB发送消息:好。
         * <接收情况
         * ClientA接收到了消息:ClientB说好。
         * ClientC接收到了消息:ClientB说好。
         * 接收情况>
         *
         */
    }
}

这里简单地模式了一下客户端之间的通信,客户端都不是直接通信的,都需要通过server来转发自己的消息,有那么一点点抽象,可以多看看。

【设计模式】中介者模式的目标是让对象的网状结构变成星形结构。_第7张图片

如果想实现一个聊天室,可以去了解以下websocket协议,然后做一个聊天室,你会发现聊天室也是使用了中介者模式。

总结

中介者模式跟组合模式非常地相似,都是用一个类去管理集合,但组合模式是屏蔽掉整体组合对象和单个对象的区别,而中介者模式是解除对象间的复杂依赖。

在使用中介者模式时,需要注意类的职责划分,一旦职责没有划分明确,会提高系统的复杂程度,适得其反。

小黄鸡发射光波

你可能感兴趣的:(设计模式,1024程序员节,中介者模式,java)