nits.kk February 2016

How does the Command pattern decouple the sender from the receiver?

The Command pattern has an IReceiver interface with few methods and corresponding to each method there are concrete Command objects (implementing an interface ICommand with execute() method).

I have read that the client knows about the concrete receiver and concrete command and it is usually the client setting up the receiver object in the concrete command object. Then why it is said it decouples the sender and the receiver?

When the client already knows the concrete receiver then I feel this is not loose coupling and also the client in this case can directly call the APIs (methods) on the receiver object.

Answers


Andrew Williamson February 2016

Directly from Wikipedia:

The command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.

Edit

After re-reading the Gang of Four's section on the Command pattern, I thought up a better scenario. Let's say you have a GUI library, which defines the following:

public interface Command {
    public void execute();
}

public class Button {
    private Command command;

    public Button(Command command) {
        this.command = command;
    }

    public void click() {
        command.execute();
    }
}

The Button, in this case, is the receiver of a command, and your code, that creates actual instances of Buttons, is the client. Of course, when you create a button, you have to define some concrete implementations of the Command interface. But the GUI library does not need to know about these classes; all it needs is the interface. This is how the GUI code is decoupled from your code.


Fuhrmanator February 2016

Loose coupling isn't the main goal of Command

Here's the class diagram for the Command pattern from the original Design Patterns book:

Command class diagram

As you said, Client knows about the ConcreteCommand and the Receiver, so there's not decoupling there.

why it is said it decouples the sender and the receiver

My copy of the book doesn't say that's the goal of the Command pattern:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Andrew's answer touches on the fact that the logic thread is decoupled from the commands. You can maybe better see the loose coupling between Invoker and Command when you refer to the sequence diagram of the pattern described in the Design Patterns:

Command sequence diagram

Many design patterns define a Client that is loosely coupled from the variations (e.g., Visitor, Strategy, Observer, Iterator, etc.). Loose coupling is a benefit to maintainability, so-called design for change. Command is special, sin


Ravindra babu February 2016

You can think of Command pattern workflow as follows.

  1. Command declares an interface for all commands, providing a simple execute() method which asks the Receiver of the command to carry out an operation.

  2. The Receiver has the knowledge of what to do to carry out the request.

  3. The Invoker holds a command and can get the Command to execute a request by calling the execute method.

  4. The Client creates ConcreteCommands and sets a Receiver for the command.

  5. The ConcreteCommand defines a binding between the action and the receiver.

  6. When the Invoker calls execute the ConcreteCommand will run one or more actions on the Receiver.

Have a look at sample code to understand things in better way.

public class CommandDemoEx{
    public static void main(String args[]){

        // On command for TV with same invoker 
        Receiver r = new TV();
        Command onCommand = new OnCommand(r);
        Invoker invoker = new Invoker(onCommand);
        invoker.execute();

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

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

class Receiver {
    public void switchOn(){
        System.out.println("Switch on from:"+this.getClass().getSimpleName());
    }
}

class OnCommand implements Command{

    private Receiver receiver;

    public OnCommand(Receiver receiver){
        this.receiver = receiver;
    }
    public void execute(){
        receiver.switchOn();
    }
}

class Invoker {
    public Command command;

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

 

Post Status

Asked in February 2016
Viewed 2,140 times
Voted 9
Answered 3 times

Search




Leave an answer