美文网首页
中介者模式/调停者模式

中介者模式/调停者模式

作者: 凉快先生 | 来源:发表于2021-01-09 14:37 被阅读0次

    通过进销存分析

    比如 XX 超市,采购部门要采购 IBM 型号的电脑了,它是根据什么来决定采购的呢?

    - 销售情况。销售部门要反馈销售情况,畅销就多采购,滞销就不采购;

    - 库存情况。即使是畅销产品,库存都有 1000 台了,每天才卖出去 10 台,还要采购吗?

    - 采购。在特殊情况下,比如一个企业客户一下子要卖 100 台电脑,你库存里自由 80 台,怎么办?催采购部门赶快采购呀

    从以上分析来看,这三个模块都是有自己的行为,并且与其他模块之间的行为产生关联关系

    进销存类图:

    Purchase 负责采购管理,buyIBMComputer 是指定了采购 IBM 电脑,refuseBuyIBM 是不再采购 IBM 了

    public class Purchase {

        //采购IBM型号的电脑

        public void buyIBMcomputer(int number){

            //访问库存

            Stock stock = new Stock();

            //访问销售

            Sale sale = new Sale();

            //电脑的销售情况

            int saleStatus = sale.getSaleStatus();

            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电脑");

        }

    }

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

    库房 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();

        }

    }

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

    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之间变化,0代表根本就没人卖,100代表非常畅销,出一个卖一个

        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()+"台");

        }

    }

    Sale 类中的 getSaleStatus 是获得销售情况,这个当然要出现在 Sale 类中了,记住恰当的类放到恰当的类中,销售情况当然只有销售人员才能反馈出来了,通过百分制的机制衡量销售情况。

    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 电脑的销售情况为:95

    采购 IBM 电脑:100 台

    库存数量为:200

    ------销售人员销售电脑--------

    销售 IBM 电脑 1 台

    库存数量为:199

    ------库房管理人员清库处理--------

    清理存货数量为:199

    折价销售 IBM 电脑 199 台

    不再采购 IBM 电脑

    迪米特法则教育我们“每个类只和朋友类交流”,这个朋友类可不是越多越好,越多耦合性越大,改一个对象而要修改一片对象,这可不是面向对象设计所期望的,而且这还是就三个模块的情况,比较简单的一个小项目,如果有十个八个这样的模块是不是就要歇菜了,我们把进销存扩充一下,如下图的情况:

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

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

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

    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);

        }

        //中介者最重要的方法,叫做事件方法,处理多个对象之间的关系

        public abstract void execute(String str,Object...objects);

    }

    我们再来看具体的中介者,中介者可以根据业务的要求产生多个中介者(一般情况只有一个中介者)

    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")){ //销售电脑

                this.sellComputer((Integer)objects[0]);

            }else if(str.equals("sale.offsell")){ //折价销售

                this.offSell();

            }else if(str.equals("stock.clear")){ //清仓处理

                this.clearStock();

            }

        }

        //采购电脑

        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+ "台");

            }

        }

        //销售电脑

        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();

        }

    }

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

    AbstractColleague 源码:

    public abstract class AbstractColleague {

        protected AbstractMediator mediator;

        public AbstractColleague(AbstractMediator _mediator){

            this.mediator = _mediator;

        }

    }

    采购类 Purchase 的源码如下:

    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电脑");

        }

    }

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

    Stock 类:

    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");

        }

    }

    Sale 类的源码:

    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之间变化,0代表根本就没人卖,100代表非常畅销,出1一个卖一个

        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");

        }

    }

    再来看场景类的变化

    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();

        }

    }

    在场景类中增加了一个中介者,然后分别传递到三个同事类中,三个类都具有相同的特性:只负责处理自己的活动(行为),与自己无关的活动就丢给中介者处理,从项目设计上来看,加入了中介者,设计结构清晰了很多,而且类间的耦合性大大减少,代码质量也有了很大的提升。

    通用类图为:

    从类图中看,中介者模式有以下几部分组成:

    抽象中介者(Mediator)角色:抽象中介者角色定义统一的接口用于各同事角色之间的通信。

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

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

    相关文章

      网友评论

          本文标题:中介者模式/调停者模式

          本文链接:https://www.haomeiwen.com/subject/lthcaktx.html