Design mode - (14) Command mode

1. Definition

Encapsulating a request as an object separates the responsibility of issuing the request from the responsibility of executing the request. In this way, the two communicate through the command object, which is convenient to store, transfer, call, add and manage the command object.

2. UML class diagram

  • Command role: defines the interface of the command and declares the method to execute.

  • Concrete Command: implement the command interface, which is the implementation of "virtual"; Usually, the receiver will be held and the receiver's function will be called to complete the operation to be performed by the command.

  • Receiver role: responsible for implementing and executing a request. Any class can become a receiver as long as it can implement the corresponding functions required by the command.

  • Requester (caller) role (Invoker): responsible for calling the command object to execute the request.

  • Client role: create a specific command object and set the receiver of the command object.

3. Instance

a. Background

Waiter, give me two mutton kebabs, two chicken wings and two bottles of beer. Chicken wings are gone. Order something else, meat essence. Spicy.

b. Instance

Abstract command class

public abstract class command {
     protected Barbecuer barbecuer;
     
     public command(Barbecuer barbecuer) {
           this.barbecuer = barbecuer;
     }
     public abstract void excuteCommand();
}

Roast chicken wings command

public class BakeChickenCommand extends command{
     public BakeChickenCommand(Barbecuer barbecuer) {
           super(barbecuer);
           // TODO Auto-generated constructor stub
     }
     
     @Override
     public void excuteCommand() {
           // TODO Auto-generated method stub
           barbecuer.bakeChickenWing();
     }
}

Roast mutton command

public class BakeMuttonCommand extends Command{

     public BakeMuttonCommand(Barbecuer barbecuer) {
           super(barbecuer);
           // TODO Auto-generated constructor stub
     }
     
     @Override
     public void excuteCommand() {
           // TODO Auto-generated method stub
           barbecuer.bakeMutton();
     }
}

Kebab

public class Barbecuer {

     public void bakeChickenWing() {
           // TODO Auto-generated method stub
           System.out.println("Chicken wings");
     }

     public void bakeMutton() {
           // TODO Auto-generated method stub
           System.out.println("shish kebab");
     }
}

waiter

public class Waiter {
     private List<Command> commands = new ArrayList<>();
     
     public void setCommand(Command command) {
           commands.add(command);
     }
     
     public void canceIOrder(Command command) {
           commands.remove(command);
     }
     
     public void Notify() {
           for(Command command : commands) {
                command.excuteCommand();
           }
     }
}

client

public class Client {
     public static void main(String[] args) {
           // TODO Auto-generated method stub
           Barbecuer barbecuer = new Barbecuer();
           Command command1 = new BakeChickenCommand(barbecuer);
           Command command2 = new BakeChickenCommand(barbecuer);
           
           Waiter waiter = new Waiter();
           waiter.setCommand(command1);
           waiter.setCommand(command2);
           waiter.Notify();
     }
}

4. Advantages

  • The command mode reduces the coupling degree of the system. There is no direct reference between the receiver and the requester, and they are completely decoupled

  • By using the command mode, new commands can be easily added to the system, in line with the opening and closing principle

  • Using command mode, it is easy to design a command queue (or macro command) combination command

  • Command mode provides a design and implementation scheme for request revocation and recovery

5. Shortcomings

It may cause some systems to have too many specific command classes, which will affect the use

6. Application scenario

  • The system needs to decouple the request caller and the request receiver, so that the caller and the receiver do not interact directly

  • The system needs to specify the request, queue the request and execute the request at different times. A command object and the initial caller of the request can have different life cycles

  • The system needs to support command revocation and recovery

  • The system needs to combine a set of operations to form macro commands

     

Tags: Design Pattern

Posted on Sun, 07 Nov 2021 00:42:38 -0400 by rcorlew