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

4

8

From Examples of GoF Design Patterns in Java's core libraries question, it was quoted that

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

As per my understanding of Command pattern,

Client calls Invoker => Invoker calls ConcreteCommand => ConcreteCommand calls Receiver method, which implements abstract Command method.

Have a look at this working example

Command pattern UML diagram from this article is shown as below.

enter image description here

Have a look at this code:

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 is Client
  2. Runnable interface is Command
  3. MyRunnable is ConcreteCommmand
  4. Thread is Invoker with start() method calling ConcreteCommand implementaiton ( which calls run() method)

Is Receiver missing here? Or Does MyRunnable play combined role of ConcreteCommand and Receiver?

Cliff answered 24/2, 2016 at 18:32 Comment(0)
H
4

A Receiver is optional, depending on whether the ConcreteCommmand owns the business logic to be executed. From page 238 of the book,

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.

In the original question we see an example with no receiver, because MyRunnable owns the logic to be executed. In two other answers here we see examples delegating to explicit receivers named Receiver and Account.

Herron answered 25/2, 2016 at 2:17 Comment(2)
The receiver object is the type that represents the business logic of an application. The responsibility of a command is not to own the business logic, but to expose this business logic to clients using a common and standard interface, i.e. the execute method. Then, I think that the receiver is not merely a relic of C/C++.Scintilla
I think you are partially correct. I have revised my answer.Herron
C
4

One answer has been posted here and it was removed by author immediately. While reading the answer, I have found solution.

I can simply convert above example to Command pattern UML diagram with one small change.

I can pass Receiver object to MyRunnable ( ConcreteCommand ).

Now I have changed my code as below.

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");
    }
}

Output:

 java ThreadCommand
 I am AC
Cliff answered 24/2, 2016 at 19:16 Comment(1)
And don't you know where is the Reciever in javax.swing.Action? (As I undestand it's actionPerformed(ActionEvent e) method among others really implements Command)Pasteboard
H
4

A Receiver is optional, depending on whether the ConcreteCommmand owns the business logic to be executed. From page 238 of the book,

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.

In the original question we see an example with no receiver, because MyRunnable owns the logic to be executed. In two other answers here we see examples delegating to explicit receivers named Receiver and Account.

Herron answered 25/2, 2016 at 2:17 Comment(2)
The receiver object is the type that represents the business logic of an application. The responsibility of a command is not to own the business logic, but to expose this business logic to clients using a common and standard interface, i.e. the execute method. Then, I think that the receiver is not merely a relic of C/C++.Scintilla
I think you are partially correct. I have revised my answer.Herron
S
2

I wanna give my two cents...

The original Command pattern separates the Command objects from the Receiver objects because the responsibility of the two sets are different.

Receivers own the business logic of the application. These types should exist outside the pattern. In a practical case, Receivers were probably already present in the code base, before commands.

For example, thinking to a bank application, a receiver can be represented by the following type:

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

One of the aims of the command design pattern is that of give a unified, homogeneous and standard way to execute operations on a set of objects (i.e. the receivers). They have not to care how to perform the real business logic. This will limit the reusability of the code implementing business logic.

For this reason, the Commands implementation has to forward the information to the Receiver. It follows an example.

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

In conclusion, imho, the statement in the accepted answer is not correct.

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

Scintilla answered 28/11, 2016 at 14:31 Comment(0)
L
0

Wouldn't receiver be...

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

call in the run method. Because that is receiving the action to do when the Runnable runs.

Leonleona answered 24/2, 2016 at 18:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.