22种设计模式——中介者模式

1. 概述

中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。
在这里插入图片描述
顾名思义,从中介者模式的名字你大概就可以猜测出这个模式主要是实现类似于中介的一些功能,那中介有什么功能呢?起连接的作用,连接起双方,协调沟通。这个功能在代码中体现为调节两个类的依赖关系,那调节两个类的依赖关系有什么作用呢?很简单,为了解耦。

前面简单乱推了中介者模式的作用,虽然有点勉强,但中介者模式确实就是用于解耦。我们来类比下现实生活,比如你要买房子,然后你就必须去找房主,然后你们要互相沟通许多,最后才能签合同,这个在代码中就体现为有两个类,租客和房主,两个类通过一系列交互后才能完成功能,两者具有很强的耦合度;如果你不直接找房主而是找中介,你只是需要和中介说你要房子,中介帮你去找房主租房,这样在代码中体现威威三个类租客和中介和房主,租客和中介交互,中介和房主交互,这样就实现了房主和租客的解耦。

其实还是比较好理解的,老惯例我们再从一个问题引入:假如你有一个创建和修改客户资料的对话框, 它由各种控件组成, 例如文本框 (Text­Field)、 复选框 (Checkbox) 和按钮 (Button) 等。
在这里插入图片描述
某些表单元素可能会直接进行互动。 例如, 选中 “我有一只狗” 复选框后可能会显示一个隐藏文本框用于输入狗狗的名字。 另一个例子是提交按钮必须在保存数据前校验所有输入内容。

如果直接在表单元素代码中实现业务逻辑, 你将很难在程序其他表单中复用这些元素类。 例如, 由于复选框类与狗狗的文本框相耦合, 所以将无法在其他表单中使用它。 你要么使用渲染资料表单时用到的所有类, 要么一个都不用。

现在元素间存在许多关联。 因此, 对某些元素进行修改可能会影响其他元素。那该怎么做呢?各个类之间形成了强耦合,我们要解耦,所以我们使用中介者模式,新建一个中介者类,各个元素类现在只负责属于它们自己模块的功能,而于其他模块交互的功能交给中介者类来处理。在这个例子中, 对话框 (Dialog) 类本身将作为中介者,所以修改后结构图如下:
在这里插入图片描述
讲到这里大家应该明白了,采用这种方式, 中介者模式让你能在单个中介者对象中封装多个对象间的复杂关系网。 类所拥有的依赖关系越少, 就越易于修改、 扩展或复用。

  • 总结
    1. 中介者模式用于解决多个元素之间形成了强耦合的关系,中介者模式用于解耦。
    2. 中介者新建一个中介者类,每个元素只需要关注自身逻辑,与其他元素沟通的功能交给中介者类即可。简单来说就是实现了网状结构变成星形结构。
    在这里插入图片描述
    在这里插入图片描述

2. 特点

  • 优点

    1. 单一职责原则。 你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
    2. 开闭原则。 你无需修改实际组件就能增加新的中介者。
    3. 你可以减轻应用中多个组件间的耦合情况。
    4. 你可以更方便地复用各个组件。
  • 缺点

    1. 一段时间后, 中介者可能会演化成为上帝对象(与每个类都有关联)
  • 使用场景

    1. 当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。该模式让你将对象间的所有关系抽取成为一个单独的类, 以使对于特定组件的修改工作独立于其他组件。

    2. 当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。

      应用中介者模式后, 每个组件不再知晓其他组件的情况。 尽管这些组件无法直接交流, 但它们仍可通过中介者对象进行间接交流。 如果你希望在不同应用中复用一个组件, 则需要为其提供一个新的中介者类。

    3. 如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式。由于所有组件间关系都被包含在中介者中, 因此你无需修改组件就能方便地新建中介者类以定义新的组件合作方式。


3. 实现

  • UML类图
    在这里插入图片描述

  • 角色说明

    元素并不知道其他元素的情况。 如果组件内发生了重要事件, 它只能通知中介者。 中介者收到通知后能轻易地确定发送者, 这或许已足以判断接下来需要触发的组件了。

    对于元素来说, 中介者看上去完全就是一个黑箱。 发送者不知道最终会由谁来处理自己的请求, 接收者也不知道最初是谁发出了请求。

    1. 元素:各种包含业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。 组件不知道中介者实际所属的类, 因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
    2. 中介者:接口声明了与组件交流的方法, 但通常仅包括一个通知方法。 组件可将任意上下文 (包括自己的对象) 作为该方法的参数, 只有这样接收组件和发送者类之间才不会耦合。
    3. 具体中介者:封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。
  • Java代码

    1. 中介者
      /**
       * @Author: chy
       * @Description: 中介者类,婚姻介绍所
       * @Date: Create in 16:05 2021/3/25
       */
      public interface MarriageAgency {
          // 配对
          void pair(Person person);
          // 注册会员
          void register(Person person);
      }
      
    2. 具体中介者
      /**
       * @Author: chy
       * @Description: 中介者接口实现类
       * @Date: Create in 17:05 2021/3/25
       */
      public class MarriageAgencyImpl implements MarriageAgency{
          List<Person> womenList = new ArrayList<>();
          List<Person> menList = new ArrayList<>();
          @Override
          public void pair(Person person) {
              if (person.sex == "男"){
                  for (Person woman : womenList) {
                      if (woman.age == person.request){
                          System.out.println("将"+person.name+"与"+woman.name+"送入洞房!");
                          break;
                      }
                  }
              }else {
                  for (Person man : menList) {
                      if (man.age == person.request){
                          System.out.println("将"+person.name+"与"+man.name+"送入洞房!");
                          break;
                      }
                  }
              }
          }
      
          @Override
          public void register(Person person) {
              if (person.sex == "男"){
                  menList.add(person);
              }else {
                  womenList.add(person);
              }
          }
      }
      
    3. 元素类
      /**
       * @Author: chy
       * @Description: 元素类,会员
       * @Date: Create in 16:06 2021/3/25
       */
      public class Person {
          String name;
          int age;
          String sex;
          // 要求的对象的年龄
          int request;
          // 内置中介类
          MarriageAgency marriageAgency;
      
          public Person(String name, int age, String sex, int request, MarriageAgency marriageAgency) {
              this.name = name;
              this.age = age;
              this.sex = sex;
              this.request = request;
              this.marriageAgency = marriageAgency;
          }
      
          // 寻找对象
          public void findPartner(){
              marriageAgency.pair(this);
          }
      }
      
    4. 客户端
      /**
       * @Author: chy
       * @Description: 客户端
       * @Date: Create in 16:02 2021/3/25
       */
      public class Client {
          public static void main(String[] args) {
              // 开一间婚姻介绍所
              MarriageAgencyImpl marriageAgency = new MarriageAgencyImpl();
      
              // 两个男嘉宾
              // 需求20岁的女嘉宾
              Person man1 = new Person("我", 20, "男", 20, marriageAgency);
              // 需求21岁的女嘉宾
              Person man2 = new Person("me", 21, "男", 21, marriageAgency);
      
              // 三个女嘉宾
              // 需求20岁的男嘉宾
              Person IU = new Person("IU", 20, "女",20, marriageAgency);
              // 需求21岁的男嘉宾
              Person yunEr = new Person("林允儿", 21, "女",21, marriageAgency);
              // 需求18岁的男嘉宾
              Person richWoman = new Person("富婆", 50, "女",18, marriageAgency);
      
              // 注册会员
              marriageAgency.register(man1);
              marriageAgency.register(man2);
              marriageAgency.register(IU);
              marriageAgency.register(yunEr);
              marriageAgency.register(richWoman);
      
              // 配对
             	man1.findPartner();
      		man2.findPartner();
          }
      }
      
    5. 结果
      在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值