使用Runnable类的java命令模式示例:Receiver是否丢失?

时间:2016-02-24 18:32:01

标签: java multithreading design-patterns runnable command-pattern

来自Examples of GoF Design Patterns in Java's core libraries问题,引用了

  

java.lang.Runnable的所有实现都是 Command 模式的示例。

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

客户 来电推荐人 => 邀请者致电 ConcreteCommand => ConcreteCommand 调用 Receiver 方法,该方法实现了抽象命令方法

看看这个有效的example

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

enter image description here

看一下这段代码:

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. ThreadCommand 客户
  2. Runnable 界面为命令
  3. MyRunnable ConcreteCommmand
  4. 线程 Invoker start()方法调用 ConcreteCommand 实现(调用run()方法)
  5. 接收器在这里丢失了吗?或MyRunnable是否扮演ConcreteCommand和Receiver的角色

4 个答案:

答案 0 :(得分:3)

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

我可以简单地将上面的示例转换为Command模式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

答案 1 :(得分:3)

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

  

命令可以具有多种能力。在一个极端,它仅定义接收器与执行请求的动作之间的绑定。在另一个极端,它实现了一切,而根本没有委托给接收器。

在原始问题中,我们看到一个没有接收器的示例,因为MyRunnable拥有要执行的逻辑。在另外两个答案中,我们看到代表名为ReceiverAccount的显式接收器的示例。

答案 2 :(得分:0)

接收者不会......

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

调用run方法。因为那是在Runnable运行时接收要执行的操作。

答案 3 :(得分:0)

我想给我两分钱......

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

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

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

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..
}

总之,imho,接受答案中的陈述是不正确的。

  

接收器是C / C ++的遗留物,其中要调用的方法与对象分离以调用它。