前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >这就是命令,命令模式

这就是命令,命令模式

作者头像
BUG弄潮儿
发布2021-01-18 14:14:46
3400
发布2021-01-18 14:14:46
举报
文章被收录于专栏:JAVA乐园

0x01:命令模式简介

在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个, 我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计。

命令模式:请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

UML类图如下:

主要角色分析如下:

  • Invoker:调用者,要求该命令执行这个请求,通常会持有命令对象,可以持有多个命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是相当于使用命令对象的入口。
  • Command:抽象命令,需要执行的所有命令都在这里声明,可以是接口或抽象类;
  • Receiver:接收者,真正执行命令的对象。知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者,只要它能够实现命令要求实现的相应功能。
  • ConcreteCommand:命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是常规意义上的客户端,而是在组装命令对象和接收者。或许把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

0x02:命令模式的实现

Receiver:该角色就是干活的角色, 命令传递到这里就应该被执行

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

    public void action() {
        System.out.println("命令执行了~~~");
    }

}

Command:声明执行操作的接口/抽象类

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

    protected Receiver receiver;

    public Command(Receiver receiver) {
        this.receiver = receiver;
    }

    //执行命令的方法
    abstract public void execute();

}

ConcreteCommand类:具体的Command,用于构造传递接收者,根据场景需求,具体的命令类也可能有多个

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

    //构造传递接收者
    public ConcreteCommand(Receiver receiver) {
        super(receiver);
    }

    //必须实现一个命令
    @Override
    public void execute() {
        receiver.action();
    }

}

Invoker类:接收命令,并执行命令

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

    private Command command;

    //接收命令
    public void setCommand(Command command) {
        this.command = command;
    }

    //执行命令
    public void executeCommand() {
        command.execute();
    }

}

命令模式测试代码:首先定义一个接收者,然后定义一个命令用于发送给接收者,最后再声明一个调用者,即可把命令交给调用者执行

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

    public static void main(String[] args) {
        //定义接收者
        Receiver receiver = new Receiver();
        //定义一个发送给接收者的命令
        Command command = new ConcreteCommand(receiver);
        //声明调用者
        Invoker invoker = new Invoker();

        //把命令交给调用者执行
        invoker.setCommand(command);
        //执行命令
        invoker.executeCommand();
    }

}

0x03:命令模式在JDK与开源框架中的运用

  • 多线程中的java.lang.Runable

JDK中的Runnable接口,Runnable 相当于命令模式中的抽象命令角色(Command)。Runnabl 中的run()方法就当于execute()方法。

代码语言:javascript
复制
@FunctionalInterface
public interface Runnable {

    public abstract void run();
}

只要是实现了Runnable接口的类都被认为是一个线程,相当于命令模式中的具体命令角色(ConcreteCommand

Thread就是调用者(Invoker),提供了start,join,interrupt等方法来控制“命令”也就是Runnable的执行。而Receiver则是让程序员可以自由与Runnale组合的抽象。

实际上调用线程的start()方法之后,就有资格去争抢CPU资源,而不需要编写获得CPU资源的逻辑。而线程抢到CPU资源后,就会执行run()方法中的内容,用Runnable接口把用户请求和CPU执行进行解耦。

  • 工作流引擎Activiti

Activiti是一款优秀开源软件,通过阅读源码,不但可以了解工作流引擎执行的原理,还可以增加个人的编码功力。Activiti所有执行过程都是采用命令模式进行执行。

喜欢,在看

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

本文分享自 BUG弄潮儿 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Receiver:该角色就是干活的角色, 命令传递到这里就应该被执行
  • Command:声明执行操作的接口/抽象类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档