设计模式9-命令模式

        这篇来简介一个命令模式。假如有这样的一个场景,项目组有需求组,美工组合代码组,需求组负责需求分析,美工组负责页面设计和美化,代码组负责编码和实现需求的逻辑。项目组接了一个项目,客户需要分别和需求组,美工组,代码组进行沟通,讨论需求找需求组,讨论页面找美工组,讨论实现逻辑找代码组。但是我们都知道,在开发中,有时候客户需要经常进行修改,客户需要来来回回的和这三个组进行讨论,客户每次修改相应的东西叫一个组过去,布置任务,然后出计划,每次都这样,双方都比较烦。这时候出现了命令模式,项目中出现一个接头人,客户告诉他怎么做,他复制去执行,客户告诉做什么就做什么。于是设计下面的类图:





      Command抽象类只有一个方法execute,其作用就是执行命令,子类非常坚决的实现该命令,与军队中类似,上级军官给士兵发布命令,士兵就去执行。比如客户发送一个山村页面的命令,接头人负责人Invoker接收到命令后,立刻执行DeletePageCommand的execute方法。对类图中简单说明:

      Command抽象类:客户发给我们的命令,定义三个工作组的成员变量,供子类使用;定义一个抽象方法execute,由子类来实现。

      Invoker实现类:项目接头负责人,setCommand接收客户发给我们的命令,action方法是执行客户的命令

      其中,Command抽象类是整个扩展的核心。

下面进行代码的实现:

1,定义一个抽象类,里面提取出来的抽象方法

package com.jack.command;

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

2,三个组分别实现上面的抽象类,表示需求的变化,组的具体实现行为

需求组:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 需求组
 */
public class RequirementGroup extends Group{
    /**
     * 客户要求需求组过去和他们谈
     */
    @Override
    public void find() {
        System.out.println("找到需求组....");
    }

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

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

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

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

美工组:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 美工组
 */
public class PageGroup extends Group{
    /**
     * 找到美工组
     */
    @Override
    public void find() {
        System.out.println("找到美工组....");
    }

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

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

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

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


代码组:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 代码组
 */
public class CodeGroup extends Group{
    /**
     * 客户要求代码组过去和他们谈
     */
    @Override
    public void find() {
        System.out.println("找到代码组....");
    }

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

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

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

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

3,定义命令抽象类Command

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 命令抽象类
 */
public abstract class Command {
    //把三个组都定义好,子类可以直接使用
    protected RequirementGroup rg = new RequirementGroup();//需求组
    protected PageGroup pg = new PageGroup();//美工组
    protected CodeGroup cg = new CodeGroup();//代码组
    //需要做的事情
    public abstract void execute();
}

4,定义两个测试的命令实现类

增加需求命令:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 增加需求命令
 */
public class AddRequirementCommand extends Command{
    /**
     * 执行增加一项需求的命令
     */
    @Override
    public void execute() {
        //找到需求组
        super.rg.find();
        //增加一份需求
        super.rg.add();
        //给出计划
        super.rg.plan();
    }
}

删除页面命令:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 删除页面的命令
 */
public class DeletePageCommand extends Command{
    /**
     * 执行一个删除页面的命令
     */
    @Override
    public void execute() {
        //找到页面组
        super.pg.find();
        //删除一个页面
        super.pg.delete();
        //给出计划
        super.pg.plan();
    }
}


5,定义一个命令接收的负责人Invoker

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 * 负责人
 */
public class Invoker {
    //定义命令对象,执行什么命令
    private Command command;

    public Command getCommand() {
        return command;
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    /**
     * 执行客户的命令
     */
    public void action(){
        this.command.execute();
    }
}


6,测试代码如下:

package com.jack.command;

/**
 * Created by jack on 2017/8/4.
 */
public class MainTest6 {
    public static void main(String[] args) throws CloneNotSupportedException {
        //定义接头人
        Invoker ls = new Invoker();
        //客户要求增加一项需求
        System.out.println("------------客户要求增加一项需求---------------");
        //客户给我们下命令来
        Command command = new AddRequirementCommand();
        //接头人接收到命令
        ls.setCommand(command);
        //接头人执行命令
        ls.action();
    }

}

运行测试程序,输出如下:

------------客户要求增加一项需求---------------
找到需求组....
客户要求增加一项需求.....
客户要求需求变更计划.....

     现在客户不需要知道到底是谁来执行修改的,上面的就是一个命令模式。


命令模式是一个高内聚的模式,将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。命令模式的通用类图如下:



     上面的类图,我们看到三个角色

Receive接收者:该角色就是干活的角色,命令传递到这里应该被执行的,具体到我们上面的例子中就是Group的三个实现类

Command命令角色:需要执行的所有命令都在这里声明

Invoker调用者角色:接收到命令,并执行命令


命令模式的优点:

1)类间解耦,调用者角色与接收者角色之间没有任何的依赖关系,调用者实现功能时只需要调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。  

2)可扩展性,Command的子类可以非常容易的扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。

3)命令模式结合其他模式会更优秀,命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command资料的膨胀问题。


命令模式的缺点:

   命令模式也是有缺点的,看Command的子类:如果有N个命令,问题就出来了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,在使用时需要慎重。

代码地址:https://github.com/wj903829182/springboot/tree/master/designpattern



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值