Command pattern in Java and Python Development 23.02.2017

Behavioral Design Patterns provide solution for the better interaction between objects and how to provide lose coupling and flexibility to extend easily. Following design patterns come under this category.

Command pattern allows you to encapsulate actions in objects. The key idea behind this pattern is to provide the means to decouple client from receiver.

In the Command pattern, a Command interface declares a method for executing a particular action. Concrete Command classes implement the execute() method of the Command interface, and this execute() method invokes the appropriate action method of a Receiver class that the concrete Command class contains. The Receiver class performs a particular action. A Client class is responsible for creating a concrete Command and setting the Receiver of the concrete Command. An Invoker class contains a reference to a Command and has a method to execute the Command.

In other words, it’s used to implement lose coupling in a request-response model. In Command pattern, the request is send to the Invoker and Invoker passes it to the encapsulated Command object. Command object passes the request to the appropriate method of Receiver to perform the specific action. The Client program creates the Receiver object and then attaches it to the Command. Then it creates the Invoker object and attaches the Command object to perform an action. Now when client program executes the action, it’s processed based on the Command and Receiver object.

In the Command pattern, the Invoker is decoupled from the action performed by the Receiver. The Invoker has no knowledge of the Receiver. The Invoker invokes a Command, and the Command executes the appropriate action of the Receiver. Thus, the Invoker can invoke commands without knowing the details of the action to be performed. In addition, this decoupling means that changes to the receiver’s action don’t directly affect the invocation of the action.

dp_command.gif

The classes participating in the pattern are:

  • Command declares an interface for executing an operation.
  • ConcreteCommand extends the Command interface, implementing the execute() method by invoking the corresponding operations on Receiver. It defines a link between the Receiver and the action.
  • Client creates a ConcreteCommand object and sets its Receiver.
  • Invoker asks the Command to carry out the request.
  • Receiver knows how to perform the operations;

The following sequence diagram shows the relationship in a clearer way:

dp_command_seq.png

When to use the Command design pattern

  • Parameterizes objects depending on the action they must perform.
  • Specifies or adds in a queue and executes requests at different moments in time.
  • Offers support for undoable actions (the execute() method can memorize the state and allow going back to that state).
  • Structures the system in high level operations that based on primitive operations.
  • Decouples the object that invokes the action from the object that performs the action. Due to this usage it is also known as Producer - Consumer design pattern.

Java

Here is an example of the Command pattern. We have a Command interface with an execute() method.

File Command.java.

public interface Command {
    public void execute();
}

LunchCommand implements Command. It contains a reference to Lunch, a receiver. Its execute() method invokes the appropriate action on the receiver.

File LunchCommand.java.

public class LunchCommand implements Command {
    Lunch lunch;

    public LunchCommand(Lunch lunch) {
        this.lunch = lunch;
    }

    @Override
    public void execute() {
        lunch.makeLunch();
    }
}

The DinnerCommand is similar to LunchCommand. It contains a reference to Dinner, a receiver. Its execute() method invokes the makeDinner() action of the Dinner object.

File DinnerCommand.java.

public class DinnerCommand implements Command {
    Dinner dinner;

    public DinnerCommand(Dinner dinner) {
        this.dinner = dinner;
    }

    @Override
    public void execute() {
        dinner.makeDinner();
    }
}

Lunch is a receiver.

File Lunch.java.

public class Lunch {
    public void makeLunch() {
        System.out.println("Lunch is being made");
    }
}

Dinner is also a receiver.

File Dinner.java.

public class Dinner {
    public void makeDinner() {
        System.out.println("Dinner is being made");
    }
}

MealInvoker is the invoker class. It contains a reference to the Command to invoke. Its invoke() method calls the execute() method of the Command.

File MealInvoker.java.

public class MealInvoker {
    Command command;

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

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

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

The Demo class demonstrates the command pattern. It instantiates a Lunch (receiver) object and creates a LunchCommand (concrete command) with the Lunch. The LunchCommand is referenced by a Command interface reference. Next, we perform the same procedure on the Dinner and DinnerCommand objects. After this, we create a MealInvoker object with lunchCommand, and we call the invoke() method of mealInvoker. After this, we set mealInvoker's command to dinnerCommand, and once again call invoke() on mealInvoker.

File Demo.java.

public class Demo {
    public static void main(String[] args) {
        Lunch lunch = new Lunch(); // receiver
        Command lunchCommand = new LunchCommand(lunch); // concrete command

        Dinner dinner = new Dinner(); // receiver
        Command dinnerCommand = new DinnerCommand(dinner); // concrete command

        MealInvoker mealInvoker = new MealInvoker(lunchCommand); // invoker
        mealInvoker.invoke();

        mealInvoker.setCommand(dinnerCommand);
        mealInvoker.invoke();
    }
}

Python 3

import abc

class Command(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def execute(self):
        pass

class LunchCommand(Command):
    def __init__(self, lunch):
        self.lunch = lunch

    def execute(self):
        self.lunch.make_lunch()

class DinnerCommand(Command):
    def __init__(self, dinner):
        self.dinner = dinner

    def execute(self):
        self.dinner.make_dinner()

class Lunch:
    def make_lunch(self):
        print("Lunch is being made")

class Dinner:
    def make_dinner(self):
        print("Dinner is being made")

class MealInvoker:
    def __init__(self, command):
        self.command = command

    def set_command(self, command):
        self.command = command

    def invoke(self):
        self.command.execute()

if __name__ == '__main__':
    lunch = Lunch() # receiver
    command_lunch = LunchCommand(lunch) # concrete command

    dinner = Dinner() # receiver
    command_dinner = DinnerCommand(dinner) # concrete command

    meal_invoker = MealInvoker(command_lunch); # invoker
    meal_invoker.invoke()

    meal_invoker.set_command(command_dinner)
    meal_invoker.invoke()