前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >20.设计模式--命令模式(Command模式)

20.设计模式--命令模式(Command模式)

作者头像
大猫的Java笔记
发布2021-11-18 13:24:36
3090
发布2021-11-18 13:24:36
举报
文章被收录于专栏:大猫的Java笔记大猫的Java笔记

1.定义

命令模式是一种行为型模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

作为开发人员经常会接到需求,然后根据需求进行代码编写,当然需求一般都是先产品做好原型图,UI再设计,然后前端后端开发,最后通过测试进行测试。如果这一天需求发生了变化,也就是所谓的命令。让ui改变一下图。或者让开发人员增加一个新功能。那么有了下面这样的操作。

Group是对不同人员的抽象,他们的子类包含了产品经理、ui以及开发人员。

代码语言:javascript
复制
public abstract class Group {

    //甲乙双方分开办公,你要和那个组讨论,你首先要找到这个组
    public abstract void find();

    //被要求增加功能
    public abstract void add();

    //被要求删除功能
    public abstract void delete();

    //被要求修改功能
    public abstract void change();

    //被要求给出所有的变更计划
    public abstract void plan();
}

ProductManagerGroup、UiGroup、CodeGroup分别表示产品组、UI组以及开发组

代码语言:javascript
复制
public class ProductManagerGroup extends Group{


    //客户要求需求组过去和他们谈
    @Override
    public void find() {
        System.out.println("找到需求组...");
    }

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

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

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

    //客户要求出变更计划
    @Override
    public void plan() {
        System.out.println("客户要求需求变更计划...");
    }
}
代码语言:javascript
复制
public class UiGroup extends Group{

    //客户要求需求组过去和他们谈
    @Override
    public void find() {
        System.out.println("找到美工组...");
    }

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

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

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

    //客户要求出变更计划
    @Override
    public void plan() {
        System.out.println("客户要求需求变更计划...");
    }
}
代码语言:javascript
复制
public class CodeGroup extends Group{

    //客户要求需求组过去和他们谈
    @Override
    public void find() {
        System.out.println("找到开发组...");
    }

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

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

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

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

此时如果要找产品改需求,就可以如下所示,先找到产品,然后增加功能,最后进行需求变更。

代码语言:javascript
复制
public class Test {

    public static void main(String[] args) {
        Group productManagerGroup = new ProductManagerGroup();
        productManagerGroup.find();
        productManagerGroup.add();
        productManagerGroup.plan();
    }
}
代码语言:javascript
复制
找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...

如果需要找开发人员增加功能,那么同样也是先找到开发,然后增加功能,最后需求变更。

代码语言:javascript
复制
public class Test {

    public static void main(String[] args) {
        Group codeGroup = new CodeGroup();
        codeGroup.find();
        codeGroup.add();
        codeGroup.plan();
    }
}
代码语言:javascript
复制
找到开发组...
客户要求增加一项需求...
客户要求需求变更计划...

现在如果又要找UI更改图,是不是有需要先找到UI组,然后进行对应的操作,可是这样需求一直变来变去的,如果说找的是产品经理改了对应需求,而开发人员不知道啊,那么是不是可能最后实际的效果和客户要的不一致,因为产品没给开发同步。

而且对于客户来说我每次改需求难道所有的组都要通知吗?能不能给我来一个对接的人,我的需求改动也就是命令,只是告诉和我同步的人,然后同步的人告诉所有的开发人员。如果中间加了一个中间人这样也让客户和对应的开发人员做了解耦。

2.命令模式实现

基于开发人员以及产品、美工的要求,我们加一个中间人,不然客户永远在随便单独叫人去改,改了也不给大家同步。

Command就是命令,对于客户提出的命令总要有人执行吧,所以在Command中引用了产品组、美工组以及代码组,毕竟命令来了要知道谁去做,而execute就是做事情的抽象,至于谁做,怎么做是子类应该决定的事情

代码语言:javascript
复制
public abstract class Command {

    //把三个组都定义好,子类可以直接使用
    //产品组
    protected ProductManagerGroup pmg = new ProductManagerGroup();

    //美工组
    protected UiGroup ug = new UiGroup();

    //代码组;
    protected CodeGroup cg = new CodeGroup();

    //只要一个方法,你要我做什么事情
    public abstract void execute();
}

Invoker就是中间人,客户只需要给中间人说我要改什么东西,至于究竟改谁改,都是中间人来决定,如果需要产品的原型图、ui的设计图、前端后端的代码都改动,那也是中间人来决定。

代码语言:javascript
复制
public class Invoker {

    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

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

而对于AddRequirementCommand、ChangeRequirementCommand以及DeleteRequirementCommand都是一个命令,对需求改动的命令,至于让谁做是他们来决定的,我可以让产品、美工、开发都改动,也可以只让其中一个组做改动。现在如果要改动一个需求是不是可以通知到对应的组了,同时调用者和开发者做到了解耦。

代码语言:javascript
复制
public class AddRequirementCommand extends Command{
    @Override
    public void execute() {
        super.pmg.find();
        super.pmg.add();
        super.pmg.plan();
    }
}
代码语言:javascript
复制
public class ChangeRequirementCommand extends Command{
    @Override
    public void execute() {
        super.pmg.find();
        super.pmg.change();
        super.pmg.plan();
    }
}
代码语言:javascript
复制
public class DeleteRequirementCommand extends Command{
    @Override
    public void execute() {
        super.pmg.find();
        super.pmg.delete();
        super.pmg.plan();
    }
}

现在对于客户来说只需要去找中间人,不在需要去一个一个的去找是那个组做,同时还避免了可能涉及到通知不到的组。

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        Invoker invoker = new Invoker(new AddRequirementCommand());
        invoker.action();
    }
}
代码语言:javascript
复制
找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...

命令模式中的角色

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

Command角色:就是命令,需要我执行的所有命令都这里声明;例子中就是对应的AddRequirementCommand、ChangeRequirementCommand以及DeleteRequirementCommand。

Invoker角色:调用者,接收到命令,并执行命令,例子中就是Invker类。

参考文献《设计模式之禅》

代码获取地址:https://gitee.com/bughong/design-pattern

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大猫的Java笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档