使用命令设计模式

2022-09-02 11:40:15

任何人都可以用一个简单的例子来解释命令模式吗?我尝试在互联网上搜索,但我感到困惑。


答案 1
public interface Command {
   public void execute();
}

在大多数情况下,命令是不可变的,并且包含封装按需执行的单个操作的指令。您可能还有一个运行时命令,它在执行时接受指令,但这会根据实现更深入地研究策略或装饰器模式。

在我自己看来,我认为注意命令的不可变上下文非常重要,否则命令将成为一种建议。例如:

public final class StopServerCommand implements Command {
    private final Server server;

    public StopServerCommand(Server server) { this.server = server; }

    public void execute() {
        if(server.isRunning()) server.stop();
    }
}

public class Application {
    //...
    public void someMethod() {
        stopButton.addActionListener(new ActionListener() {
            public void actionPerformed(Event e) {
                 stopCommand.execute();
            }
        });
    }
}

我个人不太喜欢命令。根据我自己的经验,它们只适用于框架回调。

如果它有帮助,想想一个隐喻意义上的命令;训练有素的士兵由他/她的指挥官指挥,并根据需要由士兵执行该命令。


答案 2

您可以将命令模式工作流考虑如下。

客户端调用 Invoker =>调用器调用 ConcreteCommand => ConcreteCommand 调用 Receiver 方法,该方法实现抽象命令方法。

来自dofactory文章的UML图

enter image description here

主要特点:

  1. Command 为所有命令声明一个接口,提供一个简单的 execute() 方法,该方法要求命令的接收器执行操作。

  2. 接收方知道该怎么做才能执行请求。

  3. 调用程序持有一个命令,并且可以通过调用 execute 方法来获取该命令以执行请求。

  4. 客户端创建 ConcreteCommands 并为该命令设置接收器

  5. ConcreteCommand 定义了操作和接收方之间的绑定。

  6. 调用程序调用执行时,ConcreteCommand 将在接收器上运行一个或多个操作。

代码片段:

interface Command {
    void execute();
}
interface Receiver {
    public  void switchOn();

}
class OnCommand implements Command{
    private Receiver receiver;

    public OnCommand(Receiver receiver){
        this.receiver = receiver;
    }
    public void execute(){
        receiver.switchOn();
    }
}
class Invoker {
    private Command command;

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

class TV implements Receiver{

     public void switchOn(){
        System.out.println("Switch on from TV");
    }
}
class DVDPlayer implements Receiver{

    public void switchOn(){
         System.out.println("Switch on from DVDPlayer");
    }
}

public class CommandDemoEx{
    public static void main(String args[]){
        // On command for TV with same invoker 
        Receiver receiver = new TV();
        Command onCommand = new OnCommand(receiver);
        Invoker invoker = new Invoker(onCommand);
        invoker.execute();

        // On command for DVDPlayer with same invoker 
        receiver = new DVDPlayer();
        onCommand = new OnCommand(receiver);
        invoker = new Invoker(onCommand);
        invoker.execute();            
    }
}

输出:

Switch on from TV
Switch on from DVDPlayer

解释:

在此示例中,

  1. 命令接口定义方法。execute()
  2. OnCommandConcreteCommand,它实现了方法。execute()
  3. 接收器是一个接口,实现者必须为方法提供实现。
  4. TVDVDPlayer是两种类型的接收器,它们像OnCommand一样传递给ConcreteCommand。
  5. 调用程序包含命令。这是将发送方与接收方分离的关键。
  6. 调用程序接收 OnCommand -> 它调用接收器 (TV) 来执行此命令。

通过使用调用程序,您可以打开电视和 DVDPlayer。如果扩展此程序,则同时关闭电视和DVDPlayer。

您可以使用命令模式

  1. 解耦命令的发送方和接收方

  2. 实现回调机制

  3. 实现撤消和重做功能

  4. 维护命令的历史记录

看看这个dzone和journaldev维基百科的文章。

源代码作为维基百科页面是简单,干净和不言自明的。

您可以实现撤消重做,如果您按照本文中引用的步骤操作