真刀实枪之中介者模式

  • 进销存管理,你管理的头大吗?

    • 你可能会说,这有啥难的,先来幅模块示意图

      • 从这个示意图可以看出,三个模块是相互依赖的,其中:
        1. 销售情况:销售部门要反馈情况,畅销就多采购
        2. 库存情况:即使是畅销产品,库存多的话也不用去采购
    • 那好,先根据现况做出类图

      • 代码

        • Purchase(采购管理)

          package com.peng.zjz;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Purchase {// 采购IBM电脑public void buyIBMComputer(int number) {// 访问库存Stock stock = new Stock();// 访问销售Sale sale = new Sale();// 电脑的销售情况int saleSatus = sale.getSaleStatus();if (saleSatus > 80) {// 销售良好System.out.println("采购" + number + "台");} else {// 销售情况不好number /= 2;// 折半采购System.out.println("采购" + number + "台");}stock.increase(number);}// 不采购IBM电脑public void refuseBuyIBM() {System.out.println("不采购IBM电脑");}
          }
          
        • Stock(存货管理)

          package com.peng.zjz;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Stock {// 开始有100的库存private static int COMPUTER_NUMBER = 100;// 库存增加public void increase(int number) {COMPUTER_NUMBER += number;System.out.println("库存容量:" + COMPUTER_NUMBER);}// 库存降低public void decrease(int number) {COMPUTER_NUMBER -= number;System.out.println("库存容量:" + COMPUTER_NUMBER);}// 获取库存容量public int getStockNumber() {return COMPUTER_NUMBER;}// 库存挺多,不需要采购,折价销售public void clearStock() {Purchase pc = new Purchase();Sale sale = new Sale();System.out.println("清理库存容量为:" + COMPUTER_NUMBER);// 要求折价销售sale.offSale();// 要求采购人员不要采购pc.refuseBuyIBM();}}
          
        • Sale(销售管理)

          package com.peng.zjz;import java.util.Random;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Sale {// 销售IBM电脑public void sellIBMComputer(int number) {// 访问库存Stock stock = new Stock();// 访问采购Purchase pc = new Purchase();// 判断库存容量是否满足当前销售量if (stock.getStockNumber() < number) {// 采购pc.buyIBMComputer(number);}System.out.println("销售:" + number + "台!");stock.decrease(number);}// 反馈销售情况--0代表没人买,100代表非常畅销,出一个买一个public int getSaleStatus() {Random rand = new Random(System.currentTimeMillis());int saleStatus = rand.nextInt(100);System.out.println("销售的情况为:" + saleStatus);return saleStatus;}public void offSale() {// 库房有多少卖多少Stock stock = new Stock();System.out.println("折价销售:" + stock.getStockNumber() + "台!");}}
          
        • Client(场景类)

          package com.peng.zjz;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Client {public static void main(String[] args) {// 采购人员采购电脑Purchase pc = new Purchase();pc.buyIBMComputer(100);// 销售人员销售电脑Sale sale = new Sale();sale.sellIBMComputer(1);// 库存清仓管理Stock stock = new Stock();stock.clearStock();}
          }
          
        • 执行结果(随机数的使用,你的结果也是随机的哦!)

          销售的情况为:24
          采购50台
          库存容量:150
          销售:1台!
          库存容量:149
          清理库存容量为:149
          折价销售:149台!
          不采购IBM电脑
          
    • 上述代码中,每个类和另外两个类都产生了关联,耦合度有点高,牵一发而动全身,现在扩展一下,如图所示

      • e!!理解也得理解半天,哈哈,写代码就快疯掉了!
      • 诶,好像有个星型网比这个更简洁些,来个图看看!
      • 有了参考,修改一下进销存管理系统
      • 相应的,修改下类图
          1. 每个对象只与中介者产生关系,各个对象之间的耦合降低
          2. 中介者Mediator中,定义了多个private修饰的方法,其目的是处理各个对象之间的依赖关系。
          3. 三个同事只负责自己的事情,与自己无关的活动都让中介者来做,结果是相同的,结构更加清晰,而且类间的耦合度大大减少,代码的质量也大幅度提高
      • 代码

        • AbstractMediator(抽象中介者)

          package com.peng.zjz2;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public  abstract class AbstractMediator {protected Purchase purchase;protected Sale sale;protected Stock stock;//构造函数public AbstractMediator() {super();purchase=new Purchase(this);sale=new Sale(this);stock=new Stock(this);}//中介者的最重要的方法--做事方法,处理多个对象间的关系public abstract void execute(String str,Object...objects);
          }
          
        • Mediator(中介者)

          package com.peng.zjz2;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Mediator extends AbstractMediator {@Overridepublic void execute(String str, Object... objects) {if (str.equals("purchase.buy")) {// 采购电脑this.buyComputer((Integer) objects[0]);} else if (str.equals("sale.sell")) {// 销售电脑this.sellComputer((Integer) objects[0]);} else if (str.equals("sale.offsell")) {// 折价销售电脑this.offSell();} else if (str.equals("stock.clear")) {// 清仓处理this.clearStock();}}// 清仓处理private void clearStock() {// 要求清仓销售super.sale.offSale();// 要求采购人员不要采购super.purchase.refuseBuyIBM();}// 折价销售private void offSell() {System.out.println("折价销售" + super.stock.getStockNumber() + "台");}// 销售电脑private void sellComputer(Integer number) {if (super.stock.getStockNumber() < number) {// 库存不够销售进行购货super.purchase.buyIBMComputer(number);}super.stock.decrease(number);}// 采购电脑private void buyComputer(Integer number) {// 电脑的销售情况int saleSatus = sale.getSaleStatus();if (saleSatus > 80) {// 销售良好System.out.println("采购" + number + "台");} else {// 销售情况不好number /= 2;// 折半采购System.out.println("采购" + number + "台");}}}
          
        • AbstractColleague(抽象同事)

          package com.peng.zjz2;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class AbstractColleague {protected AbstractMediator mediator;public AbstractColleague(AbstractMediator _mediator) {this.mediator = _mediator;}
          }
          
        • Purchase(采购管理)

          package com.peng.zjz2;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Purchase extends AbstractColleague {public Purchase(AbstractMediator _mediator) {super(_mediator);}// 采购IBM电脑public void buyIBMComputer(int number) {super.mediator.execute("purchase.buy", number);}// 不采购IBM电脑public void refuseBuyIBM() {System.out.println("不采购IBM电脑");}
          }
          
        • Sale(销售管理)

          package com.peng.zjz2;import java.util.Random;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Sale extends AbstractColleague {public Sale(AbstractMediator _mediator) {super(_mediator);}// 销售IBM电脑public void sellIBMComputer(int number) {super.mediator.execute("sale.sell", number);System.out.println("销售:" + number + "台!");}// 反馈销售情况--0代表没人买,100代表非常畅销,出一个买一个public int getSaleStatus() {Random rand = new Random(System.currentTimeMillis());int saleStatus = rand.nextInt(100);System.out.println("销售的情况为:" + saleStatus);return saleStatus;}public void offSale() {super.mediator.execute("sale.offsell");}}
          
        • Stock(库存管理)

          package com.peng.zjz2;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
          public class Stock extends AbstractColleague {public Stock(AbstractMediator _mediator) {super(_mediator);}// 开始有100的库存private static int COMPUTER_NUMBER = 100;// 库存增加public void increase(int number) {COMPUTER_NUMBER += number;System.out.println("库存容量:" + COMPUTER_NUMBER);}// 库存降低public void decrease(int number) {COMPUTER_NUMBER -= number;System.out.println("库存容量:" + COMPUTER_NUMBER);}// 获取库存容量public int getStockNumber() {return COMPUTER_NUMBER;}// 库存挺多,不需要采购,折价销售public void clearStock() {System.out.println("清理库存容量为:" + COMPUTER_NUMBER);// 要求折价销售super.mediator.execute("stock.clear");}}
          

中介者模式的定义

  • Define an Object that encapsulates how a set of objects interact.Mediator Promotes loose couping by kepping objects from referring to each other explicitly,and it lets you vary their interaction independentily.(用一个中介者封装一系列的对象交互,中介者使各个对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变她们之间的交互)
  • 类图
    • 类图中的角色
      1. Mediator:抽象中介者--定义统一的接口,用于各同事角色之间的通讯
      2. ConcreteMediator:具体中介者角色--协调各同事之间的行为,依赖于各个同事
      3. Colleague:同事角色--每一个角色都知道中介者,当需要别的同事来做的事,他就会找中介者来间接做,不会直接找自己的同事【补充:自发行为--处理自己的行为;依赖方法--依赖中介才能完成的行为】
  • 通用代码

    • Mediator

      package com.peng.zjz3;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
      public abstract class Mediator {// 定义同事类protected ConcreteColleague1 c1;protected ConcreteColleague2 c2;// 通过getter/setter方法把同事类注入进来public ConcreteColleague1 getC1() {return c1;}public void setC1(ConcreteColleague1 c1) {this.c1 = c1;}public ConcreteColleague2 getC2() {return c2;}public void setC2(ConcreteColleague2 c2) {this.c2 = c2;}// 中介者模式的业务逻辑public abstract void doSomething1();public abstract void doSomething2();}
      
    • Colleague

      package com.peng.zjz3;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
      public abstract class Colleague {protected Mediator mediator;public Colleague(Mediator _meditor) {this.mediator = _meditor;}
      }
      
    • ConcreteMediator

      package com.peng.zjz3;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
      public class ConcreteMediator extends Mediator {@Overridepublic void doSomething1() {//调用同事类的方法super.c1.selfMehtod1();super.c2.selfMehtod2();}@Overridepublic void doSomething2() {//调用同事类的方法super.c1.selfMehtod1();super.c2.selfMehtod2();}}
      
    • 同事1

      package com.peng.zjz3;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
      public class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator _meditor) {super(_meditor);}// 自有方法public void selfMehtod1() {// 处理自己的业务逻辑}// 依赖方法--自己不能处理的业务逻辑,委托给中介者处理public void depMethod1() {super.mediator.doSomething1();}}
      
    • 同事2

      package com.peng.zjz3;/*** @author kungfu~peng* @data 2017年11月20日* @description*/
      public class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator _meditor) {super(_meditor);}// 自有方法public void selfMehtod2() {// 处理自己的业务逻辑}// 依赖方法--自己不能处理的业务逻辑,委托给中介者处理public void depMethod2() {super.mediator.doSomething1();}}
      
    • 在Mediator抽象类中我们只定义了同事类的注入,而不是同事抽象类的注入--那是因为同事类是虽然有抽象,但是没有每个同事必须要完成的业务方法; 为什么同事类要使用构造函数注入中介者,而中介者则通过setter/getter来注入同事类呢?这是因为同事类必须有中介者,而中介者却可以只有部分同事类

中介者的应用

  • 中介者模式的优点

    1. 减少类间依赖
    2. 降低类间耦合
  • 中介模式的缺点
    1. 中介者会膨胀很大
    2. 中介者逻辑复杂--同事类越多的时候
  • 使用场景
    1. 量力而行--别使用后反而变得更加复杂
    2. 适用于多个对象的紧耦合的情况--蜘蛛网状的结构-->梳理成星型结构,使原本复杂的关系变得更加简单起来

实际应用

  • 中介者模式也叫调停者模式--一个对象要和N个对象交流,就像对象间的战争,很混乱,这时加入一个中心,和所有类都进行交流,中心说怎么处理就怎么处理
  • 机场调度中心--调度每一架飞机的起降
  • MCV框架中的C(Controller)--前端控制器(Font Controller),它的作用就是把M(Model,业务逻辑)和V(View,视图)隔离开,协调M和V协同工作,减少他们之间的依赖
  • 媒体网关--MSN服务器(中介者),中转站,接发信件【相反的是IPMsg--每个客户端集市客户端也是服务端】
  • 中介服务--房屋中介、出国中介--主要是省心(其实是你嫌烦吧!!)

最佳实践

  • 在中介者模式中,很少用到接口或者抽象类,这与依赖倒置的原则是冲突的,这是什么原因?

    • 既然是同事类而不是兄弟类,那就说明这些类之间是协作关系,完成不同的任务,处理不同的业务,所以不能在抽象类或接口中定义同事类中具有的方法----可以看出,继承是有高侵入性的
  • 使用时的情况
    1. N个对象之间产生了相互依赖的关系
    2. 多个对象有依赖关系,但是依赖的行为尚不确定或者有发生改变的可能-----降低变更引起的风险
    3. 产品开发(MVC框架),提升产品的性能和扩展性--稳定高效,扩展

声明

  • 摘自秦小波《设计模式之禅》第2版;
  • 仅供学习,严禁商业用途;
  • 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正。

设计模式之禅【中介者模式】相关推荐

  1. 读秦小波《设计模式之禅》 -- 工厂模式

    设计模式是一种非常有用的编程技巧,它对于代码的重构有些非常重要的作用,对于软件开发人员来说,需要理解并尝试着使用这些设计的方法. 个人感觉<设计模式之禅>这本书中讲解的非常具体,每个模式都 ...

  2. C#设计模式之十七中介者模式(Mediator Pattern)【行为型】

    一.引言 今天我们开始讲"行为型"设计模式的第五个模式,该模式是[中介者模式],英文名称是:Mediator Pattern.还是老套路,先从名字上来看看."中介者模式& ...

  3. 《研磨设计模式》chap10 中介者模式Mediator(1)简介

    1. 使用场景 如果电脑没有主板,各个配件的关系为 有主板后: 2. 中介者模式简介:各对象通过中介者来交互 //Mediator.java public interface Mediator { p ...

  4. java mediator模式_设计模式之Mediator 中介者模式 - 解道Jdon

    设计模式目录 >> 当前页 设计模式之Mediator(中介者) 板桥里人 http://www.jdon.com 2002/05/05 Mediator中介者模式定义: 用一个中介对象来 ...

  5. 设计模式之禅【原型模式】

    真刀实枪之原型模式 先发个个性化电子账单来引出今天的主角 个性化服务 一般银行都会要求个性化服务,添加一些个人信息在提示信息之前. 递送的成功率 邮件的递送成功率有一定的要求,由于大批的发送邮件,会被 ...

  6. 设计模式之禅【状态模式】

    真刀实枪之状态模式 从电梯说起 随着城市的发展,有两样东西的发明在城市的发展中起到非常重要的作用 汽车:横向发展 电梯:纵向发展 既然说电梯,那就看看电梯有哪些动作 开门 关门 运行 停止 好了,动作 ...

  7. 设计模式之禅【组合模式】

    真刀实枪之组合模式 从公司的人事架构谈起吧 公司的组织架构 从上图中可以分析出: 有分支的节点(树枝节点) 无分支的节点(叶子节点) 根节点(无父节点) 有了树状结构图,再看看类图长啥样吧! 这个类图 ...

  8. 设计模式之禅【访问者模式】

    真刀实枪之访问者模式 从员工的隐私说起 通过组合模式可以把整个员工的人员信息都整合起来形成一张企业员工信息树 通过迭代器模式可以遍历公司所有的员工 现在要把公司的所有人员的信息都汇总起来,那该怎么办, ...

  9. 设计模式之禅【代理模式】

    真刀实枪之代理模式 我是游戏至尊 "最近几年王者荣耀的热度飙升,自己打时可以体验到其中的升级乐趣,但是时间过得很快啊!自己不想打,找代练,好主意!" 作为一名程序员,先将打游戏这段 ...

  10. 设计模式之禅【迭代器模式】

    真刀实枪之迭代器模式 从整理项目说起 老板要看项目,但是有点乱,让我整理下,简单,说干就干 类图先上 代码跟上 IProject package com.peng.ddq;/*** @author k ...

最新文章

  1. html右侧浮动栏随着滚动,jQuery实现div浮动层跟随页面滚动效果
  2. 【数字信号处理】相关函数应用 ( 时差估计 | TOA 时差估计使用场景 | TDOA 时差估计使用场景 )
  3. java应用:csv文件的读写
  4. Linux下修改Swap分区大小
  5. springMvc注解之@ResponseBody和@RequestBody
  6. 取得NSDate实例各个字段的数字
  7. 《CSS揭秘》读书笔记
  8. Deep Boltzmann Machines
  9. AI空谈情怀,也是要输的 | 人机辩论大战
  10. action属性注入为null
  11. 什么叫显示动力学_ansys workbench的显示动力学分析的结束时间是指什么?怎么确定?速度载荷是指刚和碰撞物接触时的速度吗?...
  12. 物联卡、物联网卡、物联网语音卡你能分清吗?
  13. 领导力与团队管理上课笔记--上
  14. Think:研究生期间的迷茫、困惑——放平心态,奋力拼搏
  15. 6 计算机网络 待更新
  16. Spring Cloud Alibaba阿里面试题
  17. matlab 分段符号函数,Octave符号包中的分段函数?
  18. 地震勘探 01:地震波001
  19. 饿了么table排序
  20. 架构探险-轻量级微服务架构_第3部分-单活动架构+一些时髦的Dagger

热门文章

  1. 迭代算法8——近似迭代法之求定积分
  2. 慢慢的长大,慢慢的成长
  3. 力扣每日一题2021-09-17有效的数独
  4. 使用@Vaild或@Validated正则校验以及常用正则
  5. 51单片机开发实例 基于51单片机的万年历
  6. MarkMan – 马克鳗 IU好伙伴啊
  7. AES 对称加密算法
  8. 阿里云OSS图片文件和html文件无法直接打开,只能下载
  9. 可扩展标记语言XML(淅淅沥沥的小雨)
  10. flume backoff 退避算法