Writing in the front

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

Learning to address

www.bilibili.com/video/BV1G4…

www.bilibili.com/video/BV1Np…

Refer to the article

C.biancheng.net/view/1317.h…

Program source codeGitee.com/zhuang-kang…

18. Command mode

18.1 Definition and Features of the Command Mode

The Command pattern is defined as follows: ** Encapsulates a request as an object, separating the responsibility for making the request from the responsibility for executing it. ** In this way, the two communicate with each other 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. Reduce the coupling degree of the system by introducing middleware (abstract interface).
  2. Good scalability, easy to add or delete commands. Adding and deleting commands in command mode does not affect other classes and meets the open/Close principle.
  3. Macro commands can be implemented. Command mode can be combined with composite mode to assemble multiple commands into a composite command, known as a macro command.
  4. Easy to implement Undo and Redo operations. The command mode can be combined with the memo mode to realize command undo and restore.
  5. You can add additional functionality to existing commands. For example, logging, combined with the decorator pattern is more flexible.

Its disadvantages are:

  1. A large number of concrete command classes can be generated. Because each specific operation requires the design of a specific command class, this adds complexity to the system.
  2. The result of the command pattern is actually the result of the recipient’s execution, but in order to architecture in the form of commands and decouple requests from implementation, the introduction of additional type structures (requester and abstract command interface) makes it more difficult to understand. However, this is a common problem with design patterns. Abstraction inevitably increases the number of classes, and code abstraction is 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 role: Declares the interface to execute commands and has the abstract method execute() to execute commands.
  2. Concrete Command role: A Concrete implementation class of an abstract Command class, which owns the receiver object and performs the operations to be performed by the Command by invoking the receiver’s functions.
  3. Implementer/Receiver: Performs operations related to command functions and is the real implementer of specific command object services.
  4. Invoker (Invoker) role: is the sender of the request, it usually has a number of command objects, and accesses the command object to perform the request, it does not directly access the receiver.

18.2.2 Code implementation

Relationship between the class diagram

Command

package com.zhuang.command;

/ * * *@Classname Command
 * @DescriptionAbstract command class *@Date2021/3/27 * very@Created by dell
 */

public interface Command {
    void execute(a); // Just define a uniform execution method
}
Copy the code

OrderCommand

package com.zhuang.command;

/ * * *@Classname OrderCommand
 * @DescriptionSpecific command class *@Date2021/3/27 * very@Created by dell
 */

public class OrderCommand implements Command{

    // Hold the recipient object
    private SeniorChef receiver;

    private Order order;

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

    @Override
    public void execute(a) {
        System.out.println(order.getDiningTable()+"Table order:");
        for (String key : order.getFoodDic().keySet()) {
            receiver.makefood(order.getFoodDic().get(key),key);
        }
        try {
            Thread.sleep(1000); // Simulate cooking sleep for 1 second
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(order.getDiningTable()+"Dinner is ready for the table."); }}Copy the code

Order

package com.zhuang.command;

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

/ * * *@Classname Order
 * @DescriptionOrder class *@Date2021/3/27 joyfully *@Created by dell
 */

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

    // Store the name of the meal and record it
    private Map<String, Integer> foodDic = new HashMap<String, Integer>();

    public int getDiningTable(a) {
        return diningTable;
    }

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

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

    public void setFoodDic(String name, int num) { foodDic.put(name, num); }}Copy the code

SeniorChef

package com.zhuang.command;

/ * * *@Classname SeniorChef
 * @DescriptionCook class *@Date2021/3/27 what *@Created by dell
 */

public class SeniorChef {
    // The master chef class is the command Receiver

    public void makefood(int num, String foodName) {
        System.out.println(num + "ไปฝ"+ foodName); }}Copy the code

Waitor

package com.zhuang.command;

import java.util.ArrayList;

/ * * *@Classname Waitor
 * @DescriptionWaiter *@Date 2021/3/27 10:30
 * @Created by dell
 */

public class Waitor {

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

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

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

    // The order comes and the chef begins to execute the order
    public void orderUp(a) {
        System.out.println("Come to life...");
        for (int i = 0; i < commands.size(); i++) {
            Command cmd = commands.get(i);
            if(cmd ! =null) { cmd.execute(); }}}}Copy the code

Client

package com.zhuang.command;

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

public class Client {

    public static void main(String[] args) {
        / / create the order
        Order order1 = new Order();
        order1.setDiningTable(1);
        order1.getFoodDic().put("Scrambled eggs with tomatoes.".1);
        order1.getFoodDic().put("Coke in a can".2);

        Order order2 = new Order();
        order2.setDiningTable(2);
        order2.getFoodDic().put("Sour slithered potato".1);
        order2.getFoodDic().put("Wang Lao Ji".1);

        // Create the receiver
        SeniorChef receiver = new SeniorChef();
        // Encapsulate the order and receiver as command objects
        OrderCommand cmd1 = new OrderCommand(receiver, order1);
        OrderCommand cmd2 = new OrderCommand(receiver, order2);
        // Create the caller waitor
        Waitor invoke = new Waitor();
        invoke.setCommands(cmd1);
        invoke.setCommands(cmd2);

        // Call the cook at the counterinvoke.orderUp(); }}Copy the code

18.3 Application Scenarios of command Mode

  • The system needs to decouple the request caller and the request receiver so that the caller and receiver do not interact directly.
  • The system needs to specify requests, queue them, and execute them at different times.
  • The system needs to support Undo and Redo operations.

18.4 JDK source code parsing

Runable is a typical command pattern where Runnable acts as the 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(a);
}

/ / the caller
public class Thread implements Runnable {
    private Runnable target;
    
    public synchronized void start(a) {
        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);
}
Copy the code

A native method start0() is called, which calls the system method and starts a thread. The receiver is open to the programmer, who can define the receiver.

** * 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(a) { receiver.turnOFF(); }}Copy the code
/** * Test class */
public class Demo {
     public static void main(String[] args) {
         Receiver receiver = new Receiver();
         TurnOffThread turnOffThread = new TurnOffThread(receiver);
         Thread thread = newThread(turnOffThread); thread.start(); }}Copy the code

Write in the last

  • If my article is useful to you, please give me a click ๐Ÿ‘, thank you ๐Ÿ˜Š!
  • If you have any questions, please point them out in the comments section! ๐Ÿ’ช