java 带有 Runnable class 的命令模式示例:是否缺少 Receiver?

java command pattern example with Runnable class : Is Receiver missing?

Examples of GoF Design Patterns in Java's core libraries问题中引述

All implementations of java.lang.Runnable are examples of Command pattern.

根据我对命令模式的理解,

Client 调用 Invoker => Invoker 调用 ConcreteCommand => ConcreteCommand调用Receiver方法,后者实现抽象的Command方法.

看看这个工作example

来自this article的命令模式UML图如下所示。

看看这段代码:

public class ThreadCommand{
    public static void main(String args[]){
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}
class MyRunnable implements Runnable{
    public void run(){
        System.out.println("Running:"+Thread.currentThread().getName());
    }
}
  1. ThreadCommandClient
  2. Runnable界面是Command
  3. MyRunnableConcreteCommmand
  4. ThreadInvokerstart() 方法调用 ConcreteCommand 实现(其中调用 run() 方法)

是不是Receiver不见了?还是 MyRunnable 兼具 ConcreteCommand 和 Receiver?

接收者不会是...

System.out.println("Running:"+Thread.currentThread().getName()); 

调用运行方法。因为那是接收Runnable运行s.

时要做的动作

此处已发布一个答案,已被作者立即删除。在阅读答案时,我找到了解决方案。

我可以简单地将上面的示例转换为命令模式 UML 图,只需一点小改动。

我可以将 Receiver 对象传递给 MyRunnable (ConcreteCommand)

现在我已经更改了我的代码如下。

public class ThreadCommand{
    public static void main(String args[]){
        Receiver r = new AC();
        Thread t = new Thread(new MyRunnable(r));
        t.start();
    }
}
class MyRunnable implements Runnable{
    private Receiver receiver;
    public MyRunnable(Receiver r){
        this.receiver = r;
    }
    public void run(){
        receiver.execute();
    }
}
interface Receiver{
    public void execute();
}
class AC implements Receiver{
    public void execute(){
        System.out.println("I am AC");
    }
}
class Fan implements Receiver{
    public void execute(){
        System.out.println("I am Fan");
    }
}

输出:

 java ThreadCommand
 I am AC

A​​ Receiver 是可选的,取决于 ConcreteCommmand 是否拥有要执行的业务逻辑。从书的第 238 页开始,

A command can have a wide range of abilities. At one extreme it merely defines a binding between a receiver and the actions that carry out the request. At the other extreme it implements everything itself without delegating to a receiver at all.

在最初的问题中我们看到了一个没有接收者的例子,因为 MyRunnable 拥有要执行的逻辑。在这里的另外两个答案中,我们看到了委托给名为 ReceiverAccount.

的显式接收者的示例

我想给我两分钱...

原始命令模式将Command对象与Receiver对象分开,因为这两个集合的职责不同。

Receiver拥有应用程序的业务逻辑。这些类型应该存在于模式之外。在实际情况下,Receivers 可能已经存在于代码库中,在命令之前。

例如,考虑到 bank 应用程序,接收者可以用以下类型表示:

public class Account {
    private final double balance;
    // Construct omissis
    public Account deposit(double amount) {
        // Deposit code
    }
    public Account withdraw(double amount) {
        // Withdraw code
    }
}

命令设计模式的目标之一是提供一种统一、同类和标准的方式来对一组对象(即接收者)执行操作。他们不必关心如何执行真正的业务逻辑。这将限制实现业务逻辑的代码的可重用性

因此,Command 的实施必须将信息转发给 Receiver。它遵循一个例子。

public class DepositCommand implements Command {
    private final Account account;
    // An instance of Command should reprenset only a single request
    private final double amount;
    public DepositCommand(Account account, double amount) {
        this.account = account;
        this.amount = amount;
    }

    public void execute() {
        account.deposit(amount);
    }

    // Omissis..
}

总之,恕我直言,接受的答案中的陈述是不正确的。

The receiver is a relic of C/C++ in which the method to be invoked is separated from the object to invoke it on.