zoukankan      html  css  js  c++  java
  • 设计模式之中介者模式

    前言

    我们现实生活中存在很多复杂的 网状结构 的交互关系,例如每个人必须记录他(她)所有朋友的手机号,
    如果其中有人的手机号修改了,就必须通知他(她)所有的朋友一起修改,牵一发而动全身,非常复杂,
    如果将这种 网状结构 变成 星状结构,将大大降低它们之间的耦合度,添加一个中介者,
    在网上建立一个每个朋友都可以访问的通讯录,如QQ,我们修改了个人信息,其他人自然就看到了。

    定义

    用一个中介对象来封装一系列的对象交互,中介者使得各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。

    结构

    • Colleague,抽象同事类,每个同事类都知道中介者对象。
    • ConcreteColleague,具体同事类,通过中介者来和其他的同事类交互。
    • Mediator,中介者接口,定义各个同事之间需要交互的方法。
    • ConcreteMediator,具体中介者,了解并维护各个同事对象,协调各同事之间的交互关系。

    简单实现

    抽象同事类

    /**
     * 抽象同事类
     */
    public abstract class Colleague {
    
      private Mediator mediator;
    
      public Colleague(Mediator mediator) {
        this.mediator = mediator;
      }
    
      public Mediator getMediator() {
        return mediator;
      }
    
    }
    

    具体同事类

    /**
     * 具体同事类A
     */
    public class ConcreteColleagueA extends Colleague {
    
      public ConcreteColleagueA(Mediator mediator) {
        super(mediator);
      }
    
      public void someOperation() {
        getMediator().changed(this);
      }
    }
    

    另一个同事类

    /**
     * 具体同事类B
     */
    public class ConcreteColleagueB extends Colleague {
    
      public ConcreteColleagueB(Mediator mediator) {
        super(mediator);
      }
    
      public void someOperation() {
        System.out.println("ConcreteColleagueB.someOperation");
      }
    }
    

    中介者接口

    /**
     * 中介者接口
     */
    public interface Mediator {
    
      void changed(Colleague colleague);
    }
    

    具体中介者

    /**
     * 具体中介者
     */
    public class ConcreteMediator implements Mediator {
    
      private ConcreteColleagueA concreteColleagueA;
      private ConcreteColleagueB concreteColleagueB;
    
      public void setConcreteColleagueA(
          ConcreteColleagueA concreteColleagueA) {
        this.concreteColleagueA = concreteColleagueA;
      }
    
      public void setConcreteColleagueB(
          ConcreteColleagueB concreteColleagueB) {
        this.concreteColleagueB = concreteColleagueB;
      }
    
      @Override
      public void changed(Colleague colleague) {
        if (colleague == concreteColleagueA) {
          concreteColleagueB.someOperation();
        }
      }
    }
    

    客户端

    public class Client {
    
      public static void main(String[] args) {
        //中介者
        ConcreteMediator mediator = new ConcreteMediator();
        //两个同事对象
        ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
        ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
        mediator.setConcreteColleagueA(colleagueA);
        mediator.setConcreteColleagueB(colleagueB);
        //同事操作
        colleagueA.someOperation();
      }
    
    }
    

    在实际开发中,我们可以简化中介者模式,去除中介者接口,直接将中介者实现为一个单例,这样同事对象中就不需要持有中介者对象了。
    同事类也不需要有一个共同的抽象父类,任意的对象都可以成为同事。这种实现可以看做广义的中介者模式。

    /**
     * 具体中介者,单例实现
     */
    public class ConcreteMediator {
    
      private static final ConcreteMediator INSTANCE = new ConcreteMediator();
    
      private ConcreteMediator() {
    
      }
    
      public static ConcreteMediator getInstance() {
        return INSTANCE;
      }
    
      public void colleagueBOperation() {
        new ConcreteColleagueB().someOperation();
      }
    }
    

    两个具体同事类

    /**
     * 具体同事类A
     */
    public class ConcreteColleagueA {
    
      public void someOperation() {
        ConcreteMediator.getInstance().colleagueBOperation();
      }
    }
    
    /**
     * 具体同事类B
     */
    public class ConcreteColleagueB {
    
    
      public void someOperation() {
        System.out.println("ConcreteColleagueB.someOperation");
      }
    }
    

    客户端

    public class Client {
    
      public static void main(String[] args) {
        new ConcreteColleagueA().someOperation();
      }
    
    }
    

    中介者模式在SpringMVC的实现

    SpringMVC中的DispatcherServlet

    public class DispatcherServlet extends FrameworkServlet {
    
    /** List of HandlerMappings used by this servlet. */
    	@Nullable
    	private List<HandlerMapping> handlerMappings;
    
    	/** List of HandlerAdapters used by this servlet. */
    	@Nullable
    	private List<HandlerAdapter> handlerAdapters;
    
    	/** List of HandlerExceptionResolvers used by this servlet. */
    	@Nullable
    	private List<HandlerExceptionResolver> handlerExceptionResolvers;
    	/** List of ViewResolvers used by this servlet. */
    	@Nullable
    	private List<ViewResolver> viewResolvers;
    
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		HttpServletRequest processedRequest = request;
    		HandlerExecutionChain mappedHandler = null;
    		try {
    			try {
    				// Determine handler for the current request.
    				mappedHandler = getHandler(processedRequest);
    				// Determine handler adapter for the current request.
    				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    				// Actually invoke the handler.
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    		}
    	}
    }
    

    DispatcherServlet作为中介者协调具体http请求对象,Controller对象,视图View对象之间的交互。

    总结

    优点

    1. 将多个同事之间的交互封装到中介者对象中,同事对象之间低耦合。
    2. 多对多的关系变成了一对多,中介者集中控制同事之间的交互,当交互需要变化时,直接修改中介者。

    缺点

    1. 过度集中化,中介者对象可能会变得非常复杂。

    本质

    中介者模式的本质是封装交互。只要是实现封装对象之间的交互功能,就可以应用中介者模式,标准的中介者模式限制很多,只要本质不变,就可以看做中介者模式。

    使用场景

    1. 如果一组对象之间的交互关系比较复杂,相互依赖,结构混乱,这种情况下可以采用中介者模式。

    参考

    大战设计模式【21】—— 中介者模式
    设计模式的征途—22.中介者(Mediator)模式
    中介者模式(详解版)
    设计模式(十九)——中介者模式(智能家庭案例)
    Mediator Pattern
    研磨设计模式-书籍

  • 相关阅读:
    C# 通过Attribute制作的一个消息拦截器
    Newtonsoft.Json高级用法
    这些年,我收集的JavaScript代码(一)
    Storm整体架构分析
    Worker的内部工作原理
    Storm源码分析
    Storm集群部署
    Storm 官方文档翻译 --- 消息的可靠性保障
    [转] 如何快速掌握一门新技术/语言/框架
    小狗钱钱读书笔记
  • 原文地址:https://www.cnblogs.com/strongmore/p/15147289.html
Copyright © 2011-2022 走看看