Design pattern learning 16 (Java implementation) — command mode

Time:2021-7-26

Write in front

  • Take notes on learning design patterns
  • Improve the flexible use of design patterns

Learning address

https://www.bilibili.com/vide…

https://www.bilibili.com/vide…

Reference articles

http://c.biancheng.net/view/1…

Project source code
https://gitee.com/zhuang-kang/DesignPattern

18. Command mode

18.1 definition and characteristics of command mode

The command mode is defined as follows: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.

The main advantages of command mode are as follows.

  1. The coupling degree of the system is reduced by introducing middleware (abstract interface).
  2. It has good expansibility and is very convenient to add or delete commands. Using the command mode, adding and deleting commands will not affect other classes, and meet the “opening and closing principle”.
  3. Macro commands can be implemented. Command mode can be used withCombination modeCombined, multiple commands are assembled into a combined command, that is, macro command.
  4. It is convenient to realize undo and redo operations. The command mode can be combined with the memo mode described later to realize the revocation and recovery of commands.
  5. You can add additional functions to existing commands. For example, logging, combined with decorator mode, will be more flexible.

Its disadvantages are:

  1. A large number of specific command classes may be generated. Because each specific operation needs to design a specific command class, which will increase the complexity of the system.
  2. The result of the command mode is actually the execution result of the receiver. However, in order to structure and decouple the request and implementation in the form of command, additional type structure (the interface between the requester and abstract command) is introduced, which increases the difficulty of understanding. However, this is also a common problem of design patterns. Abstraction will inevitably increase the number of classes. Code separation must be more difficult to understand than code aggregation.

18.2 structure and implementation of command mode

18.2.1 structure of command mode

  1. Abstract command class (command) role: it declares the interface for executing commands and has the abstract method execute() for executing commands.
  2. Concrete command role: it is the concrete implementation class of the abstract command class. It has the receiver object and completes the operation to be executed by calling the receiver’s function.
  3. Implementer / receiver role: performs operations related to command functions and is the real implementer of specific command object business.
  4. Caller / requester role: it is the sender of a request. It usually has many command objects and executes related requests by accessing the command object. It does not directly access the receiver.

18.2.2 code implementation

Relational class diagram

Design pattern learning 16 (Java implementation) -- command mode

Command

package com.zhuang.command;

/**
 * @Classname Command
 *@ description Abstract command class
 * @Date 2021/3/27 10:25
 * @Created by dell
 */

public interface Command {
    void execute(); //  You only need to define a unified execution method
}

OrderCommand

package com.zhuang.command;

/**
 * @Classname OrderCommand
 *@ description specific command class
 * @Date 2021/3/27 10:25
 * @Created by dell
 */

public class OrderCommand implements Command{

    //Holding recipient object
    private SeniorChef receiver;

    private Order order;

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

    @Override
    public void execute() {
        System. Out. Println (order. Getdiningtable() + "order of table:";
        for (String key : order.getFoodDic().keySet()) {
            receiver.makefood(order.getFoodDic().get(key),key);
        }
        try {
            Thread.sleep(1000); // Simulated cooking sleep for 1 second
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System. Out. Println (order. Getdiningtable() + "the table is ready");
    }
}

Order

package com.zhuang.command;

import java.util.HashMap;
import java.util.Map;

/**
 * @Classname Order
 *@ description order class
 * @Date 2021/3/27 10:34
 * @Created by dell
 */

public class Order {
    //Table number
    private int diningTable;

    //Used to store and record meal names
    private Map<String, Integer> foodDic = new HashMap<String, Integer>();

    public int getDiningTable() {
        return diningTable;
    }

    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }

    public Map<String, Integer> getFoodDic() {
        return foodDic;
    }

    public void setFoodDic(String name, int num) {
        foodDic.put(name, num);

    }
}

SeniorChef

package com.zhuang.command;

/**
 * @Classname SeniorChef
 *@ description chef class
 * @Date 2021/3/27 10:27
 * @Created by dell
 */

public class SeniorChef {
    //The chef class is the receiver of the command

    public void makefood(int num, String foodName) {
        System.out.println (Num + "copy" + foodname);
    }

}

Waitor

package com.zhuang.command;

import java.util.ArrayList;

/**
 * @Classname Waitor
 *@ description waiter class
 * @Date 2021/3/27 10:30
 * @Created by dell
 */

public class Waitor {

    //You can hold many command objects
    private ArrayList<Command> commands;

    public Waitor() {
        commands = new ArrayList<Command>();
    }

    public void setCommands(Command cmd) {
        commands.add(cmd);
    }

    //The order came and the chef began to carry out the order
    public void orderUp() {
        System. Out. Println ("come to live...);
        for (int i = 0; i < commands.size(); i++) {
            Command cmd = commands.get(i);
            if (cmd != null) {
                cmd.execute();
            }
        }
    }
}

Client

package com.zhuang.command;

/**
 * @Classname Client
 *@ description command mode test class
 * @Date 2021/3/27 10:44
 * @Created by dell
 */

public class Client {

    public static void main(String[] args) {
        //Create order
        Order order1 = new Order();
        order1.setDiningTable(1);
        Order1. Getfooddic(). Put ("scrambled eggs with tomatoes", 1);
        Order1. Getfooddic(). Put ("canned coke", 2);

        Order order2 = new Order();
        order2.setDiningTable(2);
        Order2. Getfooddic(). Put ("sour shredded potato", 1);
        Order2. Getfooddic(). Put ("Wang Laoji", 1);

        //Create recipient
        SeniorChef receiver = new SeniorChef();
        //Encapsulate orders and recipients into command objects
        OrderCommand cmd1 = new OrderCommand(receiver, order1);
        OrderCommand cmd2 = new OrderCommand(receiver, order2);
        //Create caller waitor
        Waitor invoke = new Waitor();
        invoke.setCommands(cmd1);
        invoke.setCommands(cmd2);

        //Give the order to the counter and call the cook
        invoke.orderUp();


    }
}

Design pattern learning 16 (Java implementation) -- command mode

18.3 application scenario of command mode

  • 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, queue and execute requests at different times.
  • The system needs to support Undo and redo operations of commands.

18.4 JDK source code analysis

Runable is a typical command mode. Runnable plays the role of command, thread acts as the caller, and the start method is its execution method

//Command interface (Abstract command role)
public interface Runnable {
    public abstract void run();
}

//Caller
public class Thread implements Runnable {
    private Runnable target;
    
    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }
    
    private native void start0();
}

A native method start0 () will be called to call the system method and start a thread. The receiver is open to programmers. You can define the receiver yourself.

/**
 *JDK runnable command mode
 *Turnoffthread: belongs to specific
 */
public class TurnOffThread implements Runnable{
     private Receiver receiver;
    
     public TurnOffThread(Receiver receiver) {
         this.receiver = receiver;
     }
     public void run() {
         receiver.turnOFF();
     }
}
/**
 *Test class
 */
public class Demo {
     public static void main(String[] args) {
         Receiver receiver = new Receiver();
         TurnOffThread turnOffThread = new TurnOffThread(receiver);
         Thread thread = new Thread(turnOffThread);
         thread.start();
     }
}

Write at the end

  • If my article is useful to you, please give me some, thank you!
  • If you have any questions, please point them out in the comment area!

Recommended Today

Hot! Front and rear learning routes of GitHub target 144K

Hello, Sifu’s little friend. I’m silent Wang Er. Last week, while appreciating teacher Ruan Yifeng’s science and technology weekly, I found a powerful learning route, which has been marked with 144K on GitHub. It’s very popular. It covers not only the front-end and back-end learning routes, but also the operation and maintenance learning routes. As […]