首页 > 编程笔记 > Java笔记 阅读:15

命令模式(Java实现,附带实例)

命令模式有时又称为动作模式,它把已经触发的事件封装成一个对象,令用户能够针对该对象做出行动。业界很早就发现了这个模式,它也是经典的 GoF 设计模式之一。

命令模式规定了一套命令接口,使得程序能够在收到某个事件时通过该接口执行相应的动作。我们可以给命令对象设计各种参数,以详细描述某种有待执行的动作。命令对象还能够包含回调函数(callback function),以便在发生某个事件时,通知关注此事件的其他各方。有时你可以把命令对象理解成一种以面向对象的方式实现回调函数的手段。

每一个新创建出来的命令对象,其详细情况可能都不一样,因为这要根据引发该命令的事件来决定。用户可以按照预先编排好的一套方案来回应命令对象。

命令模式在JDK中的运用

在 JDK 里有个很经典的命令模式,这就是 Callable 与 Runnable 接口,它们分别位于 java.base 模块的 java.util.concurrent 包与 java.lang 包中。我们可以用实现了这些接口的类来安排某一段需要在特定场景下执行的代码。

在 JDK 中还有一些地方也用到了该模式,例如,在 java.desktop 模块的 javax.swing 包里,有一个名叫 Action 的接口,它定义了有可能出现在图形控件上的某个操作,在 Java 里有许多类都实现了这个接口。

命令模式实例演示

下面这个例子演示了 Driver 对象如何通过各种带有明确定义的命令来操控车辆。

【实例】Driver 实例把程序里出现的 start 与 stop 事件转化成相应动作并予以执行。
public static void main(String[] args) {
    System.out.println("Pattern Command, turn on/off vehicle");
    var vehicle = new Vehicle("sport-car");
    var driver = new Driver();
    driver.addCommand(new StartCommand(vehicle));
    driver.addCommand(new StopCommand(vehicle));
    driver.addCommand(new StartCommand(vehicle));
    driver.executeCommands("start_stop");
}
程序输出结果如下:

Pattern Command, turn on/off vehicle
START:Vehicle{type='sport-car', running=true}
STOP:Vehicle{type='sport-car', running=false}
START:Vehicle{type='sport-car', running=true}


这些用来表示动作的命令对象都经过适当封装,而且还能包含一些与客户代码相交互的逻辑,或是能够自行决定具体的执行步骤。

【实例】用 Java 语言的 sealed 机制强化命令模式的设计理念。
sealed interface VehicleCommand permits StartCommand, StopCommand {
    void process(String command);
}

record StartCommand(Vehicle vehicle) implements VehicleCommand {
    @Override
    public void process(String command) {
        if (command.contains("start")) { .. }
    }
}
统领各种具体命令的这个 VehicleCommand 体系能够在我们逐渐完善 Driver 功能的过程中方便地扩展(参见下图)。


图 1 用UML类图来演示Driver对象所能接受并执行的各种命令

总结

我们通过一个简单的范例演示了命令模式的作用。在该模式中,表示命令的这些类能够把命令本身跟程序中的其他逻辑区分开,而且能再包含一些对自身有用的信息。

每个命令对象都有自己的生命期,我们很容易就能用这样的对象实现出回调函数,从而在执行该命令的过程中触发另外的事件。

相关文章