设计模式之中介者模式

##场景
一个公司的“进销存“买IBM电脑系统设计,销售部门要反馈销售情况,畅销的就多采购,滞销就不采购;销售前要确定库存有货才能销售。采购部门要根据销售情况和库存情况进行采购。库存情况要根据销售情况和采购情况维护库存量。根据库存量来决定是否要打折出售。

“进销存“三个模块都有自己的香味,并且与其他的模块之间行为产生关联,类似我们的办公室“同事“各干各的活,但是彼此之间有依赖、交叉,于是彼此之间就产生紧耦合,也就是一个团队。

设计“进销存“类图
这里写图片描述

Purchase 采购管理
如果销售量大于80则表示销售良好,让采购多少台电脑就采购多少台电脑,如果销售不好,则对半采购。

public class Purchase {
    //  采购IBM电脑
    public void buyIBMcomputer(int number) {
        //访问库存
        Stock stock = new Stock();
        //访问销售
        Sale sale = new Sale();
        //查询销售状况
        int saleStatus = sale.getSaleStatus();
        //如果销售量大于80则表示销售良好,让采购多少台电脑就采购多少台电脑,如果销售不好,则对半采购。
        if (saleStatus > 80) {
            //销售状况良好
            System.out.println("采购IBM电脑:" + number + " ");
            stock.increase(number);
        } else {
            //销售状况不好 折半采购
            int buyNumber = number/2;
            System.out.println("采购IBM电脑" + buyNumber + " ");
        }
    }

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

}

Stock库存管理
如果库存量大了就要停止采购,通知销售人员,清库存,打折出售

public class Stock {
    //刚开始有100台电脑
    private static int COMPUTER_NUMBER = 100; //

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

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

    //查询库存数量
    public int getStockNumber() {
        return COMPUTER_NUMBER;
    }

    //如果库存量大了就要停止采购,通知销售人员,清库存,打折出售
    public void clearStock() {
        Purchase purchase = new Purchase();
        Sale sale = new Sale();
        System.out.println("清理存货数量" + COMPUTER_NUMBER);
        //要求折价销售
        sale.offSale();
        //要求采购不要采购
        purchase.refuseBuyIBM();
    }
}

Sale 销售管理

public class Sale {
    //销售IBM电脑
    public void sellIBMComputer(int number) {
        //访问库存
        Stock stock = new Stock();
        //访问采购
        Purchase purchase = new Purchase();
        if (stock.getStockNumber() < number) {
            //库存数量不够销售,采购电脑
            purchase.buyIBMcomputer(number);
        }
        System.out.println("销售IBM电脑"+ number + "台");
        stock.decrease(number);
    }

    //反馈销售状态, 0-100 之间变化,100 畅销 0 没人买
    public int getSaleStatus() {
        //定义随机数作为当前的销售状态
        Random rand = new Random(System.currentTimeMillis());
        int saleStatus = rand.nextInt(100);
        System.out.println("IBM电脑销售状况为" + saleStatus);
        return saleStatus;
    }

    //折价处理
    public void offSale() {
        //库房有多少卖多少
        Stock stock = new Stock();
        System.out.println("折价销售IBM电脑" + stock.getStockNumber() + "台");
    }
}

场景类

public class Client {
    public static void main(String[] args) {
        //采购人员采购电脑
        System.out.println("------采购人员采购电脑--------");
        Purchase purchase = new Purchase();
        purchase.buyIBMcomputer(100);
        //销售人员销售电脑
        System.out.println("\n------销售人员销售电脑--------");
        Sale sale = new Sale();
        sale.sellIBMComputer(1);
        //库房管理人员管理库存
        System.out.println("\n------库房管理人员管理库存--------");
        Stock stock = new Stock();
        stock.clearStock();
    }
}

输出:

------采购人员采购电脑--------
IBM电脑销售状况为9
采购IBM电脑50 

------销售人员销售电脑--------
销售IBM电脑1台
库存数量为:99

------库房管理人员管理库存--------
清理存货数量99
折价销售IBM电脑99台
不再采购IBM电脑

运行结果是我们期望的,但是发现这三个类都是相互关联的,迪米特法则认为“每个类只和朋友类交流“,这个朋友类并非越多越好,朋友类越多,耦合性就越大,修改一处就要修改一片。这不是我们所期望的,而且当前只是“进销存“如果扩展了物流、供应商、资产管理以后 关系图应该是这样的。

这里写图片描述

这是一个蜘蛛网结构,别说是写程序了,光是看懂就要晕倒一大批人。怎么解决这个问题呢?
学过计算机网络的童鞋 应该知道,网络拓扑 有三种类型:总线型、环形、星型。

蜘蛛网状的关系图,最好是梳理成星型 形状,星型网络拓扑中,每个计算机只用和中间的计算机进行数据交换,各个计算机之间不出现交互情况,这种结构简单而且稳定,只要中间的计算机不出现故障整个网络都不会发生大的故障。

##应用中介者模式
根据上面说的需求将 蜘蛛网 关系转化为 星状 关系刚好是 中介者模式 (调停者模式)的能力啊。关系图梳理如下:
这里写图片描述

每个模块之间不再相互交流,交流都通过中介者进行。每个模块都只负责自己的业务,其他的都丢给中介者处理,降低了模块间的耦合关系。类图如下:
这里写图片描述

新增两个抽象类AbstractMediator和AbstractColeague ,AbstractMediator是 具体中介者的抽象定义,AbstractColeague是同事类(同事类:指的就是 “进销存模块“)的抽象定义。

//定义抽象的好处就是又可以 定义方法也可以定义接口。
public abstract class AbstractMediator {
    protected Purchase purchase;
    protected Sale sale;
    protected Stock stock;

    //构造函数,创建中介者的时候新建了 三个同事类
    public AbstractMediator() {
        purchase = new Purchase();
        sale = new Sale();
        stock = new Stock();
    }
    //中介者中最重要的方法、事件方法,处理多个对象的关系
    public abstract void execute(String str,Object...objects);
}

Mediator 中介者,我们可以根据业务需要产生多个中介者,并划分职责。

/**
 * Created by yangyibo on 17/8/3.
 * 具体的中介者
 * 将原有的一对多 的依赖转移到了中介者的private 方法中实现,同事类只依赖中介者,减少了依赖,降低了类间的耦合。
 * 在实际项目中,中介者是按照职责划分的,每个中介者处理一个或多个类似的关联请求
 * 具体处理关系和执行,通过中介者取消了 stock、purchase、sale 多个类之间的耦合关系
 */
public class Mediator extends AbstractMediator {
    //中介者最重要的方法
    public void execute(String str, Object... objects) {
        if (str.equals("purchase.buy")) { //采购电脑
            this.buyComputer((Integer) objects[0]);
        } else if (str.equals("sale.sell")) { //销售IBM电脑
            this.sellComputer((Integer) objects[0]);
        } else if (str.equals("sale.offsell")) { //打折促销
            this.offSale();
        } else if (str.equals("stock.clear")) { //清库存
            this.clearStock();
        }
    }

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

    //销售IBM电脑
    private void sellComputer(int number) {
        //访问库存
        if (super.stock.getStockNumber() < number) {
            //库存数量不够销售,采购电脑
            super.purchase.buyIBMcomputer(number);
        }
        System.out.println("销售IBM电脑" + number + "台");
        super.stock.decrease(number);
    }

    //打折促销
    private void offSale() {
        //库房有多少卖多少
        System.out.println("折价销售IBM电脑" + stock.getStockNumber() + "台");
    }

    //清库存,停止采购,打折出售
    private void clearStock() {
        //要求折价销售
        super.sale.offSale();
        //要求采购不要采购
        super.purchase.refuseBuyIBM();
    }
}

同事类抽象

public abstract class AbstractColleague {
    protected AbstractMediator mediator;

    //传递进来中介者
    public AbstractColleague(AbstractMediator _mediator) {
        this.mediator = _mediator;

    }

调整简化Purchase 并作为同事类 继承 AbstractColleague 抽象

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 并作为同事类 继承 AbstractColleague 抽象

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("销售IBM电脑"+ number + "台");
    }

    //反馈销售状态, 0-100 之间变化,100 畅销 0 没人买
    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");
    }
}

调整简化Stock 并作为同事类 继承 AbstractColleague 抽象

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 = COMPUTER_NUMBER + number;
        System.out.println("库存数量为:" + COMPUTER_NUMBER);
    }

    //库存降低
    public void decrease(int number) {
        COMPUTER_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");
    }
}

调整 Client

/**
 * Created by yangyibo on 17/8/3.
 * 创建一个中介者,然后分别传递到三个同事类,三个同事类都只负责自己的活动,与自己无关的活动就丢给中介者。
 */
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("------销售人员销售电脑--------");
        Sale sale = new Sale(mediator);
        //卖了1台
        sale.sellIBMComputer(1);
        //库房管理人员管理库房
        System.out.println("------库房管理人员管理库房------");
        Stock stock = new Stock(mediator);
        stock.clearStock();
    }
}

结果:

通过使用 中介者角色,设计结构清晰了许多,取消了多个对象的关联或依赖关系,减少了对象的耦合性。
##定义
用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立的改变他们之间的交互。

##通用类图
这里写图片描述

##组成部分

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

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

  • Colleague 同事角色抽象,每个同事角色都继承此抽象 都知道中介者角色,与其他的同事角色通信时,通过中介者角色协作。

    每个同事类的行为分为两种:一种是同事本身的行为,处理自己的行为等,这种行为叫做自发行为(Self-Method),与其他的同事类没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。

##中介者模式的优点
中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合。
##中介者模式的缺点
中介者模式的缺点就是中介者会膨胀的很大,而且逻辑很复杂,原本N个 对象直接的相互依赖关系转为 中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。
##中介者模式的使用场景
中介者模式适合用于多个对象之间紧密耦合的情况,紧密耦合的标准是;在类图中出现了蜘蛛网状的结构。在这种情况下一定要考虑使用中介者模式,这有利于把蜘蛛网梳理为星型结构,使原本复杂混乱的关系变得清晰简单。

当出现如下情况尝试使用中介者模式:

  • N个对象之间产生了相互的依赖关系(N>2)
  • 多个对象有依赖关系,但是依赖香味尚不确定或者有发生改变的可能,这种情况下一般建议采用中介者模式,降低变更引起的风险扩散。

##中介者模式的实际应用
中介者模式也叫做调停者模式,一个对象要额N多个对象交流,就像对象之间的战争,很混乱,这个时需要加入一个中心,所有的类都和中心交流。中心说怎么处理就怎么处理。比如说生活中常见的例子:
###机场调度中心
机场调度中心 就是具体的中介者,用来调度每一架飞机的降落和起飞。比如某架飞机到机场上空了,就询问调度中心,是否可以降落,应当降落在哪个跑道,停在哪个停机坪 等情况,如果没有机场调度中心 那么飞行员 就要自己去看看有没有飞机和自己一起降落,有没有空的跑道,是否具备停机坪等情况。
###MVC框架
###中介服务

本文摘引自《设计模式之禅(第2版)》
本文源码:https://github.com/527515025/Design_pattern/tree/master/intermediary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值