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