设计模式-中介者模式(Mediator Pattern)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20967339/article/details/80791748

中介者模式以实体超市(苏宁、国美等)正常运行的采购业务,销售业务,库存业务之间的配合为例子
先看类图:
这里写图片描述
Purchase负责采购管理,buyIBMComouter是指定了采购IBM电脑,refuseBuyIBM是不再采购IBM了,程序如下:

package com.example.xpeng.myapplication;

import android.util.Log;

/**
 * Created by xpeng on 2018/6/24.
 * 采购
 */

public class Purchase {
    //采购IBM型号的电脑
    public void buyIBMcomputer(int number){
        //访问库存
        Stock stock = new Stock();
        //访问销售
        Sale sale = new Sale();

        //电脑的销售情况
        int saleStatus = sale.getSaleStatus();

        if (saleStatus>80){//销售情况良好
            Log.e("xyz","采购IBM电脑:"+number+"台");
            stock.increase(number);
        }else{//销售情况不好
            int buyNumber = number/2;
            Log.e("xyz","采购IBM电脑:"+buyNumber+"台");

        }

    }
    public void refuseBuyIBM(){
        Log.e("xyz","不再采购IBM电脑");
    }
}

Purchase定义了采购电脑的一个标准,如果销售情况比较好,大于80分,你让我采购多少我就采购多少;销售情况不好,你让我采购100台,我就采购50台,对这采购。电脑采购完毕了,肯定要放到库房中,因此要调用库存的方法,增加库存电脑数量。我们继续来看库房STock类:

package com.example.xpeng.myapplication;

import android.util.Log;

/**
 * Created by xpeng on 2018/6/24.
 */

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

    //库存增加
    public void increase(int number){
        COMPUTER_NUMBER = COMPUTER_NUMBER+number;
        Log.e("xyz","库存数量为:"+COMPUTER_NUMBER);
    }

    //库存降低
    public void decrease(int number){
        COMPUTER_NUMBER = COMPUTER_NUMBER - number;
        Log.e("xyz","库存数量为:"+COMPUTER_NUMBER);
    }

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

    //存货压力大了,就要通知采购人员不要采购了,销售人员尽快销售
    public void clearStock(){
        Purchase purchase = new Purchase();
        Sale sale = new Sale();
        Log.e("xyz","清理存货数量为:"+COMPUTER_NUMBER);
        //要求折价销售
        sale.offSale();
        //要求采购人员不要采购
        purchase.refuseBuyIBM();
    }

}

库房中毒额货物数量肯定有增加和减少了,同时库房还有一个容量显示,达到一定的容量后就要求对一些商品进行折价处理,腾出更多的空间容纳新产品,于是就有了clearStock方法,既然是清仓处理肯定就是折价销售了,于是在Sale这个类中就有了offSale方法,我们来看Sale类:

package com.example.xpeng.myapplication;

import android.util.Log;

import java.util.Random;

/**
 * Created by xpeng on 2018/6/24.
 */

public class Sale {

    //销售IBM型号的电脑
    public void sellIBMCompyter(int number){
        //访问库存
        Stock stock = new Stock();
        //访问采购
        Purchase purchase = new Purchase();

        if (stock.getStockNumber()<number){//库存数量不够销售
            purchase.buyIBMcomputer(number);
        }
        Log.e("xyz","销售IBM电脑"+number+"台");
        stock.decrease(number);
    }

    //反馈销售情况,0-100之间变化,0代表根本没人买,100代表非常畅销,出一个卖一个
    public int getSaleStatus(){
        Random random = new Random(System.currentTimeMillis());
        int saleStatus = random.nextInt(100);
        Log.e("xyz","IBM电脑的销售情况为:"+saleStatus);
        return saleStatus;

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

}

Sale类中的getSaleStatus是获得销售情况,这个当然要出现在Sale类中,记住恰当的类放在恰当的类中,销售情况当然只有销售人员才能反馈出来了,通过百分制的机制衡量销售情况。为破门再来看场景类是怎么运行的:

 private void Client() {
        //采购人员采购电脑
        Log.e("xyz","----采购人员采购电脑----");
        Purchase purchase = new Purchase();
        purchase.buyIBMcomputer(100);

        //销售人员销售电脑
        Log.e("xyz","\n----销售人员销售电脑---");
        Sale sale = new Sale();
        sale.sellIBMCompyter(1);

        //库房管理人员管理库存
        Log.e("xyz","\n----库存人员清理处理---");
        Stock stock = new Stock();
        stock.clearStock();
    }

我们在场景类中模拟了三种人员类型的活动:采购人员采购电脑,销售人员销售电脑。库管员管理库存,运行结果如下:
这里写图片描述
运行结果也是我们期望的,三个不同类型的参与者完成了各自的活动。但是…,你难道就没有发现这三个类间是彼此关联的吗?每个类都与其他两个类产生了关联关系,耦合都太高,维护成本太大。
这里写图片描述
加入了一个中介者作为三个模块的交流核心,每个模块之间不再相互交流,要交流就通过中介者进行,每个模块只负责自己的业务逻辑,不属于自己的则丢给中介者来处理,看类图:
这里写图片描述
建立了两个抽象类AbstractMeduator和AbstractColeague,每个对象只是与中介者Mediator之间产生依赖,与其他对象之间没有直接的关系,AbstractMediator的作用是把中介者的抽象定义,定义了一个抽象方法execute,我们来看源码:

package com.example.xpeng.myapplication;

/**
 * Created by xpeng on 2018/6/24.
 */

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源码:

package com.example.xpeng.myapplication;

import android.util.Log;

/**
 * Created by xpeng on 2018/6/24.
 */

public class Mediator extends AbstractMediator {

    //中介者最重要的方法
    @Override
    public void execute(String str, Object... objects) {
        if (str.equalsIgnoreCase("purchase.buy")){//采购电脑
            this.buyComputer((Integer) objects[0]);
        }else if (str.equalsIgnoreCase("sale.sell")){//销售电脑
            this.sellComputer((Integer) objects[0]);
        }else if (str.equalsIgnoreCase("sale.offsell")){//折价销售
            this.offSell();
        }else if (str.equalsIgnoreCase("stock.clear")){//清仓处理
            this.clearStock();
        }

    }

    //采购电脑
    private void buyComputer(int number){
        int saleStatus = super.sale.getSaleStatus();
        if (saleStatus>80){//销售情况良好
            Log.e("xyz","采购IBM电脑:"+number+"台");
            super.stock.increase(number);
        }else {//销售情况不好
            int buyNumber = number/2;
            Log.e("xyz","采购IBM电脑:"+buyNumber+"台");
        }
    }

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

    //折价销售电脑
    private void offSell(){
        Log.e("xyz","折价销售IBM电脑"+stock.getStockNumber()+"台");
    }

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

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

package com.example.xpeng.myapplication;

/**
 * Created by xpeng on 2018/6/24.
 */

public abstract class AbstractColleague {
    protected AbstractMediator mediator;
    public AbstractColleague(AbstractMediator _mediator){
        this.mediator =_mediator;
    }
}

采购类修改如下:

package com.example.xpeng.myapplication;

import android.util.Log;

/**
 * Created by xpeng on 2018/6/24.
 * 采购类
 */

public class PurchaseChange extends AbstractColleague{

    public PurchaseChange(AbstractMediator _mediator) {
        super(_mediator);
    }

    //采购IBM型号的电脑
    public void buyIBMcomputer(int number){
     super.mediator.execute("purchase.buy",number);
    }
    public void refuseBuyIBM(){
        Log.e("xyz","不再采购IBM电脑");
    }
}

再来看StockChange类:

package com.example.xpeng.myapplication;

import android.util.Log;

/**
 * Created by xpeng on 2018/6/24.
 * 库存类
 */

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

    public StockChange(AbstractMediator _mediator) {
        super(_mediator);
    }

    //库存增加
    public void increase(int number){
        COMPUTER_NUMBER = COMPUTER_NUMBER+number;
        Log.e("xyz","库存数量为:"+COMPUTER_NUMBER);
    }

    //库存降低
    public void decrease(int number){
        COMPUTER_NUMBER = COMPUTER_NUMBER - number;
        Log.e("xyz","库存数量为:"+COMPUTER_NUMBER);
    }

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

    //存货压力大了,就要通知采购人员不要采购了,销售人员尽快销售
    public void clearStock(){
//        Purchase purchase = new Purchase();
//        Sale sale = new Sale();
        Log.e("xyz","清理存货数量为:"+COMPUTER_NUMBER);
//        //要求折价销售
//        sale.offSale();
//        //要求采购人员不要采购
//        purchase.refuseBuyIBM();
      super.mediator.execute("stock.clear");
    }

}

再看看销售类:

package com.example.xpeng.myapplication;

import android.util.Log;

import java.util.Random;

/**
 * Created by xpeng on 2018/6/24.
 */

public class SaleChange extends AbstractColleague{

    public SaleChange(AbstractMediator _mediator) {
        super(_mediator);
    }

    //销售IBM型号的电脑
    public void sellIBMCompyter(int number){
       super.mediator.execute("sale.sell",number);
        Log.e("xyz","销售IBM电脑"+number+"台");

    }

    //反馈销售情况,0-100之间变化,0代表根本没人买,100代表非常畅销,出一个卖一个
    public int getSaleStatus(){
        Random random = new Random(System.currentTimeMillis());
        int saleStatus = random.nextInt(100);
        Log.e("xyz","IBM电脑的销售情况为:"+saleStatus);
        return saleStatus;

    }
    //折价处理
    public void offSale(){
        //库房有多少卖多少
        super.mediator.execute("sale.offsell");
    }

}

再来看场景类的变化:

 private void ClientChange() {
        AbstractMediator mediator = new Mediator();
        //采购人员采购电脑
        Log.e("xyz","----采购人员采购电脑----");
        PurchaseChange purchase = new PurchaseChange(mediator);
        purchase.buyIBMcomputer(100);

        //销售人员销售电脑
        Log.e("xyz","\n----销售人员销售电脑---");
        SaleChange sale = new SaleChange(mediator);
        sale.sellIBMCompyter(1);

        //库房管理人员管理库存
        Log.e("xyz","\n----库存人员清理处理---");
        StockChange stock = new StockChange(mediator);
        stock.clearStock();
    }

在场景类中增加了一个中介者,然后分别传递到三个同事类中,三个类都具有相同的特性:只负责处理自己的活动,与自己无关的活动就丢给中介者处理,程序运行的结果是相同的。从项目设计上来说,加入中介者,设计结构清晰了很多,而且类间的耦合性大大减少了,代码质量也有了很大的提升。
以上讲解的模式就是中介者模式,在多个对象依赖的情况下,通过加入中介者角色,取消了多个对象的关联或依赖关系,减少了对象的耦合性,其通用类图为:
这里写图片描述
从类图中看,中介者模式有几下部分组成:
抽象中介者(Mediator)角色:抽象中介者角色定义统一的接口用于各个同时角色之间的通信。
具体中介者(Concreate Mediator)角色:具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同时角色。
同事(Colleague)角色:每一个同事角色都知道中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。每个同事类的行为分两种:一种是同事本身的行为,比如改变对象本身的状态,处理自己的行为等等,这种方法叫做自发行为(Self-Method),与其他的同事类或中介者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。
为什么同事类要使用构造函数注入而中介者使用getter/setter方式注入同事类呢?想过没有?那是因为同事类必须有中介者,而中介者可以只有部分同事类。
中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然也减少了类间的耦合。它的缺点呢就是中介者会膨胀的很大,而且逻辑会很负责,因为所有的原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就复杂。
大家可以在如下的情况下尝试使用中介者模式:
1、N个对象之间产生了相互的依赖关系,其中N大于2,注意是相互的依赖;
2、多个对象有依赖关系,但是依赖的行为尚不确定或者有发生改变的可能,在这种情况下一般建议采用中介者模式,降低变更引起的风险扩散
3.产品开发。其中一个明显的例子就是MVC框架,把这个应用到产品中,可以提升产品的性能和扩展性。

中介者模式DEMO下载地址:

demo下载

猜你喜欢

转载自blog.csdn.net/qq_20967339/article/details/80791748