中介者模式【Mediator Pattern】,什么是中介者模式?作用?主要对象?优缺点?应用场景?实现案例?

目录


设计模式专栏目录(点击进入…)



什么是中介者模式?

中介者模式(Mediator Pattern)是一种行为型设计模式,其目的是通过引入一个中介者对象来封装对象之间的交互和通信,使得各个对象不再直接相互依赖,避免系统中的类彼此过度耦合。中介者对象在这里扮演了“中间人”的角色,负责调度和协调其他对象的行为。


中介者模式的作用?

(1)减少对象之间的耦合

在中介者模式下,各个对象通过中介者进行通信,而不需要直接引用彼此,从而降低对象间的依赖性。

(2)优化对象通信逻辑

通过将复杂的对象交互逻辑集中到中介者中,便于维护和扩展。

(3)提高系统的可扩展性和可维护性

各个对象只需要关注自身的功能逻辑,不需要关心与其他对象的交互实现。


中介者模式的主要对象

(1)中介者(Mediator)

定义对象间交互的接口;其中包含了各个同事类。

(2)具体中介者(Concrete Mediator)

负责实际的对象间通信与协调。

(3)抽象同事类(Colleague)

需要与其他对象交互的对象,但它们通过中介者进行通信。其中包含了中介者。。

(4)具体同事类(Concrete Colleague)

同事类的具体实现,承担各自的功能,并依赖中介者进行间接的通信。


中介者模式的优缺点

优点

(1)降低耦合度

对象之间不再直接相互依赖,只需与中介者打交道,减少了复杂的对象关系。

(2)集中控制交互

将交互行为集中到一个地方,有利于简化类的设计和逻辑实现。

(3)更好的扩展性

由于中介者模式隔离了对象的直接交互,因此添加或修改参与者的交互变得更加简单。

缺点

(1)中介者的复杂性增加

随着系统变大,中介者对象的逻辑可能会变得非常复杂,承担了过多的责任,导致难以维护。

(2)可能导致性能问题

如果中介者处理了过多的交互,可能引发性能瓶颈,特别是在涉及大量通信的场景中。


中介者模式应用场景

(1)GUI开发

在图形界面应用中,各个组件(如按钮、文本框等)之间可能需要进行频繁交互,而中介者可以简化这些交互的逻辑。

(2)网络协议栈

在协议栈的实现中,不同层之间的通信可以通过中介者进行协调。

(3)消息中间件

在系统设计中,中介者模式可以用于消息中间件,处理不同系统之间的消息传递和通信。


中介者模式实现案例

公司,给员工发薪水的地方,那公司就要想尽办法盈利赚钱,盈利方法则不尽相同,但是作为公司都有相同三个环节:采购、销售和库存,这个怎么说呢?

比如:一个软件公司,要开发软件,需要开发环境吧, Windows 操作系统,数据库产品等,这你得买吧,那就是采购,开发完毕一个产品还要把产品推销出去,推销出去了大家才有钱赚,不推销出
去大家都去喝西北风呀,既然有产品就必然有库存,软件产品也有库存,你总要拷贝吧,虽然是不需要占用库房空间,那也是要占用光盘或硬盘,这也是库存。

比如:做咨询服务的公司,它要采购什么?
采购知识,采购经验,这是这类企业的生存之本,销售的也是知识和经验,库存同样是知识和经验。尽然进销存是这么的重要,我们今天就来讲讲它的原理和设计,我相信很多人都已经开发过这种类型的软件,基本上都形成了固定套路,不管是单机版还是网络版,一般的做法都是通过数据库来完成相关产品的管理,相对来说还是比较简单的项目。

三个模块之间的示意图如下:
在这里插入图片描述

从上的示意图上可以看出:三个模块是相互依赖的,基本上是你中有我,我中有你,为什么呢?

就以一个终端销售商(什么是终端销售商?就是以服务最终客户为目标的企业,比如 XX 超市,国美电器等等)为例子,比如采购部门要采购 IBM 型号的电脑了,它是根据什么来决定采购的呢?根据两个要素:
销售情况。销售部门要反馈销售情况,畅销就多采购,滞销就不采购;
库存情况。即使是畅销产品,库存都有 1000 台了,每天才卖出去 10 台,还要采购吗?!

销售模块是企业的盈利核心,也是对其他两个模块有影响的:
库存情况。库房有货,才能销售,没货空手套白狼是不行的;

督促采购。在特殊情况下,比如一个企业客户一下子要卖 100 台电脑,你库存里自由 80 台,怎么办?
催采购部门赶快采购呀! 同样的,库存管理也对其他两个模块有影响,库房是有容积限制的,不可能无限大,所以就有了清仓处理,那就要求采购部门别采购了,同时销售部门赶快打折销售。

上面是三个模块的情况,比较简单的一个小项目,如果有十个八个这样的模块是不是就要歇菜了,我们把进销存扩充一下,如下图的情况:
在这里插入图片描述

是不是看到一个蜘蛛网的结构,这个别说是编写程序了,就是给人看估计能让一大批的人昏倒!每个
对象都要和其他的几个对象交流,对象越多,每个对象要交流的成本也就越多了,就单独维护这些对象的交流基本上就能让一大批程序员望而却步,这明摆着不是人干的活嘛!从这方面来,我们已经发现设计的缺陷,作为一个架构师,发现缺陷就要想办法来修改,我们思考一下,怎么来修改。

再上学的时候学习计算机讲过一些网络的基本知识,还记得网络拓扑有几种类型吗?

总线型,环型,星型,我们来想想星型拓扑是什么什么样子的,如下图:

在这里插入图片描述

星型网络拓扑中每个计算机通过交换机和其他计算机进行数据交换,各个计算机之间并没有直接出现
交互的情况,结构简单,而且稳定,只要中间那个交换机不瘫痪,整个网络就不会发生大的故障,公司和网吧一般都采用星型网络,那也说明星型拓扑是深得民心,那我们来想想是不是可以把这种星型结构引入到我们的设计中呢?

示意图:

在这里插入图片描述

加入了一个中介者作为三个模块的交流核心,每个模块之间不再相互交流,要交流就通过中介者进行, 每个模块只负责自己的业务逻辑,不属于自己的则丢给中介者来处理。

类图:

在这里插入图片描述

建立了两个抽象类 AbstractMediator 和 AbstractColeague,每个对象只是与中介者 Mediator 之间产
生依赖,与其他对象之间没有直接的关系,AbstractMediator 的作用是把中介者的抽象定义,定义了一个抽象方法 execute。

从类图中看,中介者模式有以下几部分组成:
(1)抽象中介者(Mediator)角色
抽象中介者角色定义统一的接口用于各同事角色之间的通信。

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

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

1、抽象中介者(AbstractMediator)

package com.uhhe.common.design.mediator;

/**
 * 抽象中介者
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:40
 */
public abstract class AbstractMediator {

    protected Purchase purchase;
    protected Sale sale;
    protected Stock stock;

    public AbstractMediator() {
        purchase = new Purchase(this);
        sale = new Sale(this);
        stock = new Stock(this);
    }

    /**
     * 中介者最重要的方法,叫做事件方法,处理多个对象之间的关系
     *
     * @param str     事件方法字符串
     * @param objects 参数
     */
    public abstract void execute(String str, Object... objects);

}

2、具体中介者(Mediator )

中介者 Mediator 有定义了多个 private 方法,其目标是处理各个对象之间的依赖关系,即是说把原有
一个对象要依赖多个对象的情况移到中介者的 private 方法中实现,在实际项目中,一般的做法是中介者按照职责进行划分,每个中介者处理一个或多个类似的关联请求。

package com.uhhe.common.design.mediator;

/**
 * 具体中介者
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:40
 */
public class Mediator extends AbstractMediator {

    @Override
    public 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();
        }
    }

    /**
     * 采购电脑
     *
     * @param number 采购数目
     */
    private void buyComputer(int number) {
        int saleStatus = super.sale.getSaleStatus();
        if (saleStatus > 80) { //销售情况良好
            System.out.println("采购IBM电脑:" + number + "台");
            super.stock.increase(number);
        } else { //销售情况不好
            int buyNumber = number / 2; //折半采购
            System.out.println("采购IBM电脑:" + buyNumber + "台");
        }
    }

    /**
     * 销售电脑
     *
     * @param number 销售数目
     */
    private void sellComputer(int number) {
        if (super.stock.getStockNumber() < number) {
            //库存数量不够销售
            super.purchase.buyIBMcomputer(number);
        }
        super.stock.decrease(number);
    }

    /**
     * 折价销售电脑
     */
    private void offSell() {
        System.out.println("折价销售IBM电脑" + stock.getStockNumber() + "台");
    }

    /**
     * 清仓处理
     */
    private void clearStock() {
        // 要求清仓销售
        super.sale.offSale();
        // 要求采购人员不要采购
        super.purchase.refuseBuyIBM();
    }

}

3、抽象同事类(AbstractColleague)

package com.uhhe.common.design.mediator;

/**
 * 同事类
 * 
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:40
 */
public abstract class AbstractColleague {

    protected AbstractMediator mediator;

    public AbstractColleague(AbstractMediator mediator) {
        this.mediator = mediator;
    }

}

4、具体同事类(Concrete Colleague)

下面类是不是简化了很多,看着也清晰了很多,处理自己的职责,与外界有关系的事件处理则交
给了中介者来完成。

采购

package com.uhhe.common.design.mediator;

/**
 * 采购
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:41
 */
public class Purchase extends AbstractColleague {

    public Purchase(AbstractMediator mediator) {
        super(mediator);
    }

    /**
     * 采购IBM型号的电脑
     *
     * @param number 采购数量
     */
    public void buyIBMcomputer(int number) {
        super.mediator.execute("purchase.buy", number);
    }

    /**
     * 不在采购IBM电脑
     */
    public void refuseBuyIBM() {
        System.out.println("不再采购IBM电脑");
    }

}

销售

package com.uhhe.common.design.mediator;

import java.util.Random;

/**
 * 销售
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:41
 */
public class Sale extends AbstractColleague {

    public Sale(AbstractMediator mediator){
        super(mediator);
    }

    /**
     * 销售IBM型号的电脑
     * @param number 销售数量
     */
    public void sellIBMComputer(int number){
        super.mediator.execute("sale.sell", number);
        System.out.println("销售IBM电脑"+number+"台");
    }

    /**
     * 反馈销售情况,0——100之间变化,0代表根本就没人卖,100代表非常畅销,出1一个卖一个
     * @return 销售情况
     */
    public int getSaleStatus(){
        Random rand = new Random(System.currentTimeMillis());
        int saleStatus = rand.nextInt(100);
        System.out.println("IBM电脑的销售情况为:"+saleStatus);
        return saleStatus;
    }

    /**
     * 折价处理
     */
    public void offSale(){
        super.mediator.execute("sale.offsell");
    }

}

库存

package com.uhhe.common.design.mediator;

/**
 * 库存
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:41
 */
public class Stock extends AbstractColleague {

    public Stock(AbstractMediator mediator) {
        super(mediator);
    }

    /**
     * 刚开始有100台电脑
     */
    private static int COMPUTER_NUMBER = 100;

    /**
     * 库存增加
     *
     * @param number 增加数目
     */
    public void increase(int number) {
        COMPUTER_NUMBER = COMPUTER_NUMBER + number;
        System.out.println("库存数量为:" + COMPUTER_NUMBER);
    }

    /**
     * 库存降低
     *
     * @param number 降低数目
     */
    public void decrease(int number) {
        COMPUTER_NUMBER = COMPUTER_NUMBER - number;
        System.out.println("库存数量为:" + COMPUTER_NUMBER);
    }

    /**
     * 获得库存数量
     *
     * @return 库存数量
     */
    public int getStockNumber() {
        return COMPUTER_NUMBER;
    }

    /**
     * 存货压力大了,就要通知采购人员不要采购,销售人员要尽快销售
     */
    public void clearStock() {
        System.out.println("清理存货数量为:" + COMPUTER_NUMBER);
        super.mediator.execute("stock.clear");
    }

}

5、使用场景(Client)

package com.uhhe.common.design.mediator;

/**
 * 使用场景
 * 
 * @author nizhihao
 * @version 1.0.0
 * @date 2024/9/8 15:42
 */
public class Client {

    public static void main(String[] args) {
        AbstractMediator mediator = new Mediator();
        //采购人员采购电脑
        System.out.println("------采购人员采购电脑--------");
        Purchase purchase = new Purchase(mediator);
        purchase.buyIBMcomputer(100);

        //销售人员销售电脑
        System.out.println("\n------销售人员销售电脑--------");
        Sale sale = new Sale(mediator);
        sale.sellIBMComputer(1);

        //库房管理人员管理库存
        System.out.println("\n------库房管理人员清库处理--------");
        Stock stock = new Stock(mediator);
        stock.clearStock();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值