zoukankan      html  css  js  c++  java
  • 简说设计模式——中介者模式

    一、什么是中介者模式

      中介这个词并不陌生,就是房屋中介的那个“中介”,就是中间人的意思。比如MVC模式,C(Controller控制器)是M(Model模型)和V(View视图)的中介者,在前后端交互时起到了中间人的作用。

      中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。UML结构图如下:

      其中,Mediator是抽象中介者,定义了同事对象到中介者对象的接口;Colleague是抽象同事类;ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令;ConcreteColleague是具体同事类,每个具体同事只知道自己的行为,而不了解其它同事类的情况,但它们却都认识中介者对象。

      1. 抽象中介者

      抽象中介者角色定义统一的接口,用于各同事角色之间的通信。

    1 public abstract class Mediator {
    2     
    3     //抽象的发送消息方法
    4     public abstract void send(String message, Colleague colleague);
    5     
    6 }

      2. 抽象同事类

      每一个同事角色都知道中介者角色,而且与其它的同事角色通信的时候,一定要通过中介者角色协作。每个同事类的行为分两种:一种是同事本身行为,比如改变对象本身的状态,处理自己的行为等,这种行为叫做自发行为,与其它同事类或者中介者没有任何依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法。

    1 public abstract class Colleague {
    2     
    3     protected Mediator mediator;
    4     
    5     public Colleague(Mediator mediator) {
    6         this.mediator = mediator;
    7     }
    8 
    9 }

      3. 具体中介者类

      具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。

     1 public class ConcreteMediator extends Mediator {
     2 
     3     private ConcreteColleague1 colleague1;
     4     private ConcreteColleague2 colleague2;
     5     
     6     public void setColleague1(ConcreteColleague1 colleague1) {
     7         this.colleague1 = colleague1;
     8     }
     9 
    10     public void setColleague2(ConcreteColleague2 colleague2) {
    11         this.colleague2 = colleague2;
    12     }
    13 
    14     @Override
    15     public void send(String message, Colleague colleague) {
    16         if(colleague == colleague1) {
    17             colleague2.notify(message);
    18         } else {
    19             colleague1.notify(message);
    20         }
    21     }
    22 
    23 }

      4. 具体同事类

      这里以ConcreteColleague1为例,ConcreteColleague2不再赘述。

     1 public class ConcreteColleague1 extends Colleague {
     2 
     3     public ConcreteColleague1(Mediator mediator) {
     4         super(mediator);
     5     }
     6     
     7     public void send(String message) {
     8         mediator.send(message, this);
     9     }
    10     
    11     public void notify(String message) {
    12         System.out.println("同事1得到消息:" + message);
    13     }
    14 
    15 }

      5. Client客户端

      首先创建一个具体中介者对象,然后实例化两个具体同事类并与该中介者进行绑定,colleague1与colleague2通过中介者发送信息。

     1 public class Client {
     2     
     3     public static void main(String[] args) {
     4         ConcreteMediator mediator = new ConcreteMediator();
     5         
     6         ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
     7         ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
     8         
     9         mediator.setColleague1(colleague1);
    10         mediator.setColleague2(colleague2);
    11         
    12         colleague1.send("Nice to meet u.");
    13         colleague2.send("Nice to meet u too.");
    14     }
    15 
    16 }

      运行结果如下:
      

    二、中介者模式的应用

      1. 何时使用

    • 多个类相互耦合,形成网状结构时

      2. 方法

    • 将网状结构分离为星型结构

      3. 优点

    • 减少类间依赖,降低了耦合
    • 符合迪米特原则

      4. 缺点

    • 中介者会膨胀的很大,而且逻辑复杂

      5. 使用场景

    • 系统中对象之间存在比较复杂的引用关系
    • 想通过一个中间类来封装多个类的行为,而又不想生成太多的子类

      6. 应用实例

    • 联合国/WTO作为中介者协调各个国家
    • 房屋中介/机场调度系统
    • MVC框架,其中C(Contorller控制器)是M(Model模型)和V(View视图)的中介者

      7. 注意事项

    • 不应当在职责混乱时使用

    三、中介者模式的实现

      上面我们有提到,联合国作为一个由各国代表组成,用来维护国际和平与安全,解决国际间经济、社会、文化和人道主义性质的问题的角色,它就是一个调停者、中介者的角色,国与国直接完全完全可以通过“联合国”这个中介者来发生关系,而不用直接通信。

      下面就以联合国安理会作为中介者,了解一下中介者模式。UML图如下:

      1. 联合国机构

      抽象中介者。

    1 public abstract class UnitedNations {
    2     
    3     public abstract void declare(String message, Country country);
    4 
    5 }

      2. 国家类

      抽象国家类,需声明中介者角色。

    1 public class Country {
    2     
    3     protected UnitedNations unitedNations;
    4     
    5     public Country(UnitedNations unitedNations) {
    6         this.unitedNations = unitedNations;
    7     }
    8 
    9 }

      3. 具体国家类

      具体国家类,继承了抽象国家类。这里以USA类为例,Iraq类不再赘述。

     1 public class USA extends Country {
     2 
     3     public USA(UnitedNations unitedNations) {
     4         super(unitedNations);
     5     }
     6     
     7     public void declare(String message) {
     8         unitedNations.declare(message, this);
     9     }
    10     
    11     public void getMessage(String message) {
    12         System.out.println("美国获得对方信息:" + message);
    13     }
    14 
    15 }

      4. 联合国安理会

      具体中介者角色,继承抽象中介者,重写其declare()方法,对不同国家发送不同信息。

     1 public class UnitedNationsSecurityCouncil extends UnitedNations {
     2 
     3     private USA usa;
     4     private Iraq iraq;
     5     
     6     public void setUsa(USA usa) {
     7         this.usa = usa;
     8     }
     9 
    10     public void setIraq(Iraq iraq) {
    11         this.iraq = iraq;
    12     }
    13 
    14     @Override
    15     public void declare(String message, Country country) {
    16         if(country == usa) {
    17             iraq.getMessage(message);
    18         } else {
    19             usa.getMessage(message);
    20         }
    21     }
    22 
    23 }

      5. Client客户端

      实例化一个联合国安理会对象,两国通过联合国安理会进行对话。

     1 public class Client {
     2 
     3     public static void main(String[] args) {
     4         
     5         UnitedNationsSecurityCouncil UNSC = new UnitedNationsSecurityCouncil();
     6         
     7         USA usa = new USA(UNSC);
     8         Iraq iraq = new Iraq(UNSC);
     9         
    10         UNSC.setUsa(usa);
    11         UNSC.setIraq(iraq);
    12         
    13         usa.declare("不准研制核武器");
    14         iraq.declare("我们没有核武器");
    15     }
    16 
    17 }

      运行结果如下:

      

      源码地址:https://gitee.com/adamjiangwh/GoF 

  • 相关阅读:
    HDU2149-Public Sale
    分页和多条件查询功能
    hdu 4691 最长的共同前缀 后缀数组 +lcp+rmq
    BZOJ 2588 Count on a tree (COT) 是持久的段树
    windows 设置脚本IP
    hdu 4912 Paths on the tree(树链拆分+贪婪)
    分散式-ubuntu12.04安装hadoop1.2.1
    struts详细解释拦截器
    Codeforces 459E Pashmak and Graph(dp+贪婪)
    C#中的数据格式转换 (未完待更新)
  • 原文地址:https://www.cnblogs.com/adamjwh/p/10959987.html
Copyright © 2011-2022 走看看