设计模式之中介者模式与命令模式

一、引言:
中介者模式用于处理多个类高耦合的场景,类似于星型拓扑结构,在该结构中抽象出一个中介者,并配备同事类,实现不同的业务逻辑。
在这里插入图片描述
该模式有三部分组成:中介者-同事-业务实现类。
抽象中介者定义统一的接口,用于各同事角色之间通信,具体中介者用于协调各同事角色最终的协作,必须依赖各个同事,同事角色不能与其他同事类有依赖,如果需要的话,必须通过中介者才能完成。
中介者的模式好处是减少类中的依赖,降低了类间的耦合;但是缺点是同事类越多,中介者的逻辑就越复杂。
该模式适用的场景:机场调度中心、MVC框架、媒体网关、中介服务等。

二、中介者demo:
我们假定一个经销商采购、库存和销售电脑。使用中介者模式实现电脑的采购存储和售卖。紧抓上面的三部分,首先是中介者:

/** 抽象中介者 */
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);
}

抽象中介者首先实例化具体的业务实现类,下面是具体中介者,执行具体的任务:

/** 具体中介者 */
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();
    }
}

接下来是抽象同事类和具体同事类:

/** 抽象同事类 */
abstract class AbstractColleague {
    protected AbstractMediator mediator;

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

/** 采购管理 */
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电脑");
    }
}

/** 库存管理 */
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");
    }
}

/** 销售管理 */
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代表非常畅销, 出一个卖一个
    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 MediatorDesign {
    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();
    }
}

client端代码只需要实例化中介者,然后通过中介者去实现具体的需求和业务,至于是如何实现的,这不是client端需要了解的问题。

三、命令模式:
命令模式是一种高内聚的设计模式:
在这里插入图片描述
命令模式使用的场景:GUI开发中的按钮点击等。
命令模式的思路:client-Invoker-command-receiver。假如对于一款软件开发,client类似现实生活中的用户,Invoker则相当于软件的产品经理,Invoker通过command去指挥下面的receiver,receiver是谁?就是软件开发的需求组,前端,后端,UI等等。对应用户而言,希望的是我对软件的看法或者意见直接给产品经理反馈,至于找谁来做,那不是用户关心的事。这个模式尽量保证client少跟receiver打交道,该模式的优点是架构清晰明了,但是有一个缺点是如果命令很多的话,那么继承command的子类也会非常多。

四、命令模式demo:

package com.example.javatestlib;

/** 抽象组 */
abstract class Group {
    //甲乙双方分开办公, 如果你要和某个组讨论, 你首先要找到这个组
    public abstract void find();
    //被要求增加功能
    public abstract void add();
    //被要求删除功能
    public abstract void delete();
    //被要求修改功能
    public abstract void change();
    //被要求给出所有的变更计划
    public abstract void plan();
}

/** 需求组 */
class RequirementGroup extends Group {

    public void find() {
        System.out.println("找到需求组...");
    }

    public void add() {
        System.out.println("客户要求增加一项需求...");
    }

    public void change() {
        System.out.println("客户要求修改一项需求...");
    }

    public void delete() {
        System.out.println("客户要求删除一项需求...");
    }

    public void plan() {
        System.out.println("客户要求需求变更计划...");
    }
}

/** 美工组 */
class PageGroup extends Group {

    public void find() {
        System.out.println("找到美工组...");
    }

    public void add() {
        System.out.println("客户要求增加一个页面...");
    }

    public void change() {
        System.out.println("客户要求修改一个页面...");
    }

    public void delete() {
        System.out.println("客户要求删除一个页面...");
    }

    public void plan() {
        System.out.println("客户要求页面变更计划...");
    }
}

/** 代码组 */
class CodeGroup extends Group {
    //客户要求代码组过去和他们谈
    public void find() {
        System.out.println("找到代码组...");
    }

    public void add() {
        System.out.println("客户要求增加一项功能...");
    }

    public void change() {
        System.out.println("客户要求修改一项功能...");
    }

    public void delete() {
        System.out.println("客户要求删除一项功能...");
    }

    public void plan() {
        System.out.println("客户要求代码变更计划...");
    }
}

/** 命令抽象类 */
abstract class Command {
    /* 把三个组都定义好, 子类可以直接使用 */
    protected RequirementGroup rg = new RequirementGroup(); //需求组
    protected PageGroup pg = new PageGroup(); //美工组
    protected CodeGroup cg = new CodeGroup(); //代码组

    public abstract void execute();
}

/** 命令具体类:增加需求类 */
class AddRequirementCommand extends Command {
    public void execute() {
        super.rg.find();
        super.rg.add();
        super.rg.plan();
    }
}

/** 命令具体类:删除页面类 */
class DeletePageCommand extends Command {
    public void execute() {
        super.pg.find();
        super.rg.delete();
        super.rg.plan();
    }
}

/** 负责人invoker */
class Invoker {
    /* 管理命令 */
    private Command command;
    /* 客户发出的命令 */
    public void setCommand(Command command){
        this.command = command;
    }
    /* 执行客户的命令 */
    public void action(){
        this.command.execute();
    }
}



public class CommondDesign {
    public static void main(String[] args) {

        Invoker xiaoSan = new Invoker();

        System.out.println("------------客户要求增加一项需求---------------");

        Command command = new AddRequirementCommand();

        xiaoSan.setCommand(command);

        xiaoSan.action();
    }
}

博客参考书籍:秦小波 《设计模式之禅(第2版)》

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值