Java Code DesignPartten

设计模式-命令模式

Posted on 2020-09-14,5 min read

定义

  • Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能)
  • 组成
    • Receive接收者角色:干活的角色,命令传递到这里被执行
    • Command命令角色:需要执行的所有命令都在这里声明
    • Invoker调用者角色:接收到命令并且执行命令

优点

  • 类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需要调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行
  • 可扩展性:Command子类可以非常容易的扩展,调用者Invoker和高层模块之间不产生严重的耦合
  • 命令模式可以和其他模式结合:
    • 和责任链模式:实现命令族解析任务
    • 和模板方法模式:减少Command子类膨胀的问题

缺点

  • Command子类会膨胀的非常大

使用场景

  • 场景:只要你觉得是命令的地方就可以使用命令模式

代码

命令模式

通用类图

命令模式通用类图

为了方便描述,这里采用:甲方向外包提需求的场景

类图

命令模式类图

代码

抽象接收者(抽象类

package com.pattern.command;

public abstract class Receiver {
    // 抽象接收者,每个接收者都必须完成的业务
    public abstract void finishCommand();

}

代码组(继承自抽象接收者)[具体接收者]

package com.pattern.command;

public class CodeGroup extends Receiver {
    @Override
    public void finishCommand() {
        System.out.println("这是所有接收者都能执行的命令,当前命令是哦代码组接受的");
    }
    public void designCode(){
        System.out.println("代码组设计页面");
    }
    public void tellPageGroup(){
        System.out.println("代码组告诉和美工组协调");
    }
    public void plan(){
        System.out.println("代码组规划计划");
    }
    public void changeCode(){
        System.out.println("代码组修改代码");
    }
    public void deleteCode(){
        System.out.println("代码组删除代码");
    }
    public void addCode(){
        System.out.println("代码组添加代码");
    }
}

美工组(继承自抽象接收者)[具体接收者]

package com.pattern.command;

/**
 * 美工外包,接受美工方面的命令
 */
public class PageGroup extends Receiver {

    @Override
    public void finishCommand() {
        System.out.println("这是所有接收者都能执行的命令,当前命令是美工组接受的");
    }
    public void designPage(){
        System.out.println("美工组设计页面");
    }
    public void tellCodeGroup(){
        System.out.println("美工组告诉代码组修改代码");
    }
    public void plan(){
        System.out.println("美工组规划计划");
    }
    public void changePage(){
        System.out.println("美工组修改页面");
    }
    public void deletePage(){
        System.out.println("美工组删除页面");
    }
    public void addPage(){
        System.out.println("美工组添加页面");
    }
}

抽象命令类(抽象类

package com.pattern.command;

public abstract class Command {
    protected CodeGroup codeGroup = new CodeGroup();
    protected PageGroup pageGroup = new PageGroup();
    // 执行当前命令
    public abstract void executeCommand();
    public void rollback(){
        System.out.println("回滚方法,用于处理没有完成就中断的命令。根据日志或者其他回滚");
    }
}

增加页面命令(继承自抽象命令类)[具体命令]

package com.pattern.command;

/**
 * 具体的一个命令,增加页面命令
 */
public class InsertCommand extends Command {
    @Override
    public void executeCommand() {
        super.pageGroup.plan();
        super.pageGroup.designPage();
        super.pageGroup.tellCodeGroup();
        super.codeGroup.plan();
        super.codeGroup.changeCode();
    }
}

删除页面命令(继承自抽象命令类)[具体命令]

package com.pattern.command;

/**
 * 删除一个页面的具体命令
 */
public class DeleteCommand extends Command {
    @Override
    public void executeCommand() {
        super.pageGroup.plan();
        super.pageGroup.deletePage();
        super.pageGroup.tellCodeGroup();
        super.codeGroup.plan();
        super.codeGroup.deleteCode();
    }
}

执行者(普通类

package com.pattern.command;

/**
 * 调用者,负责接受高层的命令并且执行
 */
public class Invoker {
    private  Command command;

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

测试代码

package com.pattern;

import com.pattern.command.*;
import org.junit.Test;

public class CommandTest {
    @Test
    public void test(){
        System.out.println("--------定义一个执行者--------");
        Invoker invoker = new Invoker();
        System.out.println("--------甲方发来了一个增加页面的命令--------");
        Command command = new DeleteCommand();
        System.out.println("--------执行者执行甲方的命令--------");
        invoker.setCommand(command);
        invoker.execute();
    }
}

结果

命令模式执行结果

注意

  • 命令模式有可能会撤回(任务没执行完成突然取消了),解决方法有两种、
    • 结合备忘录模式还原最后状态,该方法适合接收者为状态变更的情况,而不适合事件处理
    • 增加一个新的命令,实现事件的回滚

下一篇: 设计模式-中介者模式→

loading...