Behavioral mode - command mode

Command mode

1 Definition

Encapsulating a request as an object separates the responsibility of sending the request from the responsibility of executing the request, so that the two communicate through the command object, which is convenient for storing, transmitting, calling, adding and managing the command object.

2 Structure

The command mode contains the following roles:

  • Abstract command class role: define the command interface and declare the execution method
  • Specific command role: a specific command, which implements the command interface, usually holds the receiver and calls the receiver's function to complete the operation to be executed by the command
  • Implementer / receiver role: receiver, the object that actually executes the command. Any class may become a receiver, as long as it can implement the corresponding functions required by the command
  • Caller / requester role: when a command object is required to execute a request, it usually holds a command object. It can hold many command objects. This is where the client really triggers the command and requires the command to perform corresponding operations, that is, it is equivalent to using the entry of the command object

3 Implementation

order:

  • Attendant: the caller role, she initiates the command
  • Cook: the role of receiver, the object of real command execution
  • Order: the order is included in the command
//Order class
public class Order {
    //Table number
    private int diningTable;
    //Meals and servings
    private Map<String,Integer> foodDir = new HashMap<>();

    //Initialize table number
    public Order(int diningTable) {
        this.diningTable = diningTable;
    }
    //Get table number
    public int getDiningTable() {
        return diningTable;
    }

    //Get the meals included in the order
    public Map<String, Integer> getFoodDir() {
        return foodDir;
    }

    //Save meals
    public void setFood(String foodName,Integer foodNum) {
        foodDir.put(foodName, foodNum);
    }
}
//Chef (receiver)
public class SeniorChef {
    //Making food
    public void makeFood(String foodName,Integer foodNum){
        System.out.println("Made"+foodNum+"share"+foodName);
    }
}
//Abstract command class
public interface Command {
    //Execution method
    void execute();
}
//Specific command class
public class OrderCommand implements Command{
    //Aggregate order class and chef class
    private Order order;
    private SeniorChef seniorChef;

    public OrderCommand(Order order, SeniorChef seniorChef) {
        this.order = order;
        this.seniorChef = seniorChef;
    }

    @Override
    public void execute() {
        System.out.println(order.getDiningTable()+"Start preparing the order for the table");
        //Get the meals in the order
        Map<String, Integer> foodDir = order.getFoodDir();
        Set<String> strings = foodDir.keySet();
        for (String string : strings) {
            seniorChef.makeFood(string,foodDir.get(string));
        }
        System.out.println(order.getDiningTable()+"The order for the table is ready");
        System.out.println();
    }
}
//Waiter (requester)
public class Waiter {
    //Hold multiple command objects
    private List<Command> commands = new ArrayList<>();

    public void setCommand(Command command) {
        commands.add(command);
    }

    //Initiate command
    public void orderUp(){
        System.out.println("Here comes the new order");
        for (Command command : commands) {
            if(command != null){
                command.execute();
            }
        }
    }
}
//Test class
public class Test {
    public static void main(String[] args) {
        //Table 1 order
        Order order1 = new Order(1);
        //Food
        order1.setFood("double cooked pork slices",1);
        order1.setFood("cola",2);
        order1.setFood("rice",2);

        //Order for table 2
        Order order2 = new Order(2);
        //Food
        order2.setFood("Elbow",1);
        order2.setFood("Sprite",1);
        order2.setFood("rice",1);

        //Create a waiter class to execute the request
        Waiter waiter = new Waiter();
        waiter.setCommand(new OrderCommand(order1,new SeniorChef()));
        waiter.setCommand(new OrderCommand(order2,new SeniorChef()));
        waiter.orderUp();
    }
}

Test results:
Here comes the new order
Order preparation for table 1
Made a pot of pork
Made two portions of rice
Made two cokes
Order ready for table 1

Order preparation for table 2
Made a share of rice
Made an elbow
Made a sprite
The order for table 2 is ready

4 advantages and disadvantages

advantage:

  • Reduce the coupling degree of the system: the command mode can decouple the object calling the operation from the object implementing the operation (the caller and the receiver are decoupled)
  • Adding or deleting commands is very convenient: using the command mode, adding and deleting commands will not affect other classes. It meets the "opening and closing principle" and is flexible for expansion
  • Macro command can be realized: command mode can be combined with combined mode to assemble multiple commands into a combined command, that is, macro command
  • Facilitate undo and restore operations. Command mode can be combined with memo mode to realize command revocation and recovery

5 usage scenarios

  • The system needs to decouple the request caller and receiver so that the caller and receiver do not interact directly
  • The system needs to specify the request at different times, queue the request and execute the request
  • The system needs to support command revocation and recovery

6 JDK source code analysis

Runnable is a typical command mode. Runnable plays the role of command, Thread acts as the requester, start method is its execution method, and the receiver is open. It is defined by our programmers (the class that implements the runnable interface defined by ourselves).

Keywords: Design Pattern

Added by Domcsore on Sun, 23 Jan 2022 10:39:35 +0200