[design mode] tap more than 200 lines of code to explain the command mode!

What is Command mode

concept

Command Pattern is a behavioral pattern. It is defined as encapsulating a request as an object, so that you can parameterize customers with different requests; Queue or log requests, and support revocable operations. The command mode pays attention to decoupling and delay. For example, thread is a typical example of the command mode. If the command mode is not applicable, the method we want to execute cannot be handed over to the thread for execution, and the method must be executed immediately.

For example, when we go to a restaurant for dinner, the waiter will give us a menu. This menu is a written "command". We only need to tell the waiter (requester) what dish (command) we want to eat, and the waiter will inform the chef (implementer) what dish to cook. If we think the dish is enough, we can also cancel the dishes we haven't cooked; There is also the remote control of the TV. When we want to change channels, we pick up the remote control (requester) and press the buttons (commands) of other channels. The TV (implementer) will change channels. We want to go back and see it. Just click back.

In fact, I've been thinking about the role of "we" in these two examples, and "we" is a role outside the command mode module. If we want to realize the requirements, we have to call the requester, such as ordering. You can directly tell the cook that the cook will pay attention to you, and it's useless for you to shout directly to the TV. Here we can also realize that the requester encapsulates how to use the command. We only need to interact with the requester if we want to use it.

The command mode is also very similar to opening the command operation interface of Windows or Linux. We only need to enter commands and parameters to execute functions.

advantage

  1. Reduce the coupling of the system. By introducing objects such as commands, the coupling between requester and implementer is reduced.
  2. Comply with the principle of open and closed. To add an operation, just write a new command class.
  3. It can delay execution, revoke and queue requests.

Most of the design patterns are for understanding coupling and high cohesion. I'm a little tired of writing.

shortcoming

  1. It increases the complexity of the system. Using the command mode may cause the system to produce a large number of command classes. Each operation has to implement a corresponding command class. A large number of command classes will increase the complexity of the system.
  2. Reduces the readability of the code. Using command mode separates the requester from the implementer by command, which not only brings difficulties in code design, but also increases the difficulty of system understanding.

Most of the design patterns are difficult to implement and increase the complexity of the system.

principle

"+" means compliance, "-" means non-compliance or irrelevant

principleOpen and closedSingle responsibilityDimittRichter substitutionDependency inversionInterface isolationSynthetic multiplexing
++--+--

Applicable scenario

  1. Event driven module. For example, the buttons of the browser and the console of the operating system are triggered by an action or a line of command, and the corresponding operation needs to be completed.
  2. The requester and implementer are required to be decoupled. Requesters and implementers do not interact directly.
  3. There are situations where execution can be delayed, revoked, rolled back, etc. Such as logging and saving information to the database.

How

To implement command mode, you need the following four things:

  1. Abstract command interface: it is used to declare commands and has the abstract method execute() to execute commands.
  2. Specific command class: implement the abstract command interface and call the implementer to complete the function.
  3. Implementer / receiver class: provides services for specific command classes.
  4. Requester / caller class: the caller of the command, responsible for managing and executing the command.

Upper class graph

Here I copy the class diagram of command mode seen in other websites. You can have a look, and then look at the code I wrote.

Above example

When summer comes, every household has installed air conditioners. There is a company that installs and maintains air conditioners. The leaders of the company are responsible for arranging the installation and maintenance of air conditioners for the workers. After receiving the work, the workers go to install and repair them.

Class diagram:

code:

/**
 * Created on 2021/6/4.
 *
 * @author xuxiaobai
 */
public class CommandTest {
    public static void main(String[] args) {
        //leader
        Leader leader=new Leader();
        //Only Zhang San is a worker
        Worker worker = new Worker("Zhang San");
        System.out.println("Leadership arrangement");
        leader.addPlan(new InstallWork("A 58 town", worker));
        leader.addPlan(new RepairWork("B 23 town", worker));
        //Hey, the leader cancelled the arrangement
        leader.cancel();
        //Rearrange
        leader.addPlan(new InstallWork("C No. 15, town", worker));
        leader.addPlan(new InstallWork("D Town 8", worker));
        leader.addPlan(new InstallWork("E Town 6", worker));

        System.out.println("Leaders give orders");
        leader.order();
        /**
         * result:
         * Leadership arrangement
         * Cancel work arrangement
         * Leaders give orders
         * Zhang San got on his beloved van and arrived at No. 15, C town
         * Zhang San began to work
         * Remove the air conditioner
         * Internal machine
         * External loading machine
         * test
         * Finish work
         * Zhang San got on his beloved van and arrived at No. 8, D town
         * Zhang San began to work
         * Remove the air conditioner
         * Internal machine
         * External loading machine
         * test
         * Finish work
         * Zhang San got on his beloved van and arrived at No. 6, E town
         * Zhang San began to work
         * Remove the air conditioner
         * Internal machine
         * External loading machine
         * test
         * Finish work
         */
    }
}


/**
 * Implementer / receiver class
 * Worker
 * Functions: arrive at the destination, install air conditioner and repair air conditioner
 */
class Worker{

    private String name;
    //Do you carry an air conditioner
    private boolean airConditioner=false;

    public Worker(String name){
        this.name=name;
    }

    /**
     * terminus ad quem
     * @param address
     */
    public void arrive(String address){
        System.out.print(name+"I got on my beloved van and arrived");
        System.out.println(address);
    }

    /**
     * Bring the air conditioner
     */
    public void getAirConditioner(){
        this.airConditioner=true;
    }

    /**
     * Put down the air conditioner
     */
    private void putAirConditioner(){
        this.airConditioner=false;
    }

    /**
     * Install air conditioner
     */
    public void installAirConditioner(){
        System.out.println(name+"Start working");
        System.out.println("Remove the air conditioner");
        putAirConditioner();
        System.out.println("Internal machine");
        System.out.println("External loading machine");
        System.out.println("test");
        System.out.println("Finish work");
    }


    /**
     * Repair air conditioner
     */
    public void repairAirConditioner(){
        System.out.println(name+"Start working");
        System.out.println("Remove the outer casing");
        System.out.println("inspect");
        System.out.println("Remove the inner casing");
        System.out.println("inspect");
        System.out.println("repair");
        System.out.println("Finish work");
    }


}

/**
 * Abstract command interface
 * You can only use interfaces here, so you can use interfaces. If you want to write an example, you can consider writing an abstract class
 * Work class
 */
interface Work{
    void execute();
}

/**
 * Specific command class
 * Install air conditioner
 */
class InstallWork implements Work{
    //address
    private String address;
    //worker
    private Worker worker;
    //Receive air conditioning certificate
    private boolean voucher=false;

    public InstallWork(String address,Worker worker){
        this.address=address;
        this.worker=worker;
        this.voucher=true;
    }


    @Override
    public void execute() {
        if (voucher){
            //The air conditioner can be accessed only when there is a certificate
            worker.getAirConditioner();
        }else {
            System.out.println("I didn't get the air conditioner certificate, so I couldn't get the air conditioner");
            return;
        }
        worker.arrive(address);
        worker.installAirConditioner();
    }
}

/**
 * Specific command class
 * Repair air conditioner
 */
class RepairWork implements Work{
    //address
    private String address;
    //worker
    private Worker worker;

    public RepairWork(String address,Worker worker){
        this.address=address;
        this.worker=worker;
    }


    @Override
    public void execute() {
        worker.arrive(address);
        worker.repairAirConditioner();
    }
}

/**
 * Leaders of air conditioning company
 */
class Leader{
    List<Work> works=new ArrayList<>();

    /**
     * Increase work arrangement
     * @param work
     */
    public void addPlan(Work work){
        works.add(work);
    }

    /**
     * Distribution work
     */
    public void order(){
        Iterator<Work> iterator = works.iterator();
        while (iterator.hasNext()){
            Work work = iterator.next();
            work.execute();
            iterator.remove();
        }
    }

    /**
     * Cancel arrangement
     */
    public void cancel(){
        System.out.println("Cancel work arrangement");
        works.clear();
    }

}


Let's take a brief look and sort out our ideas.

If we don't use the command mode, we have to operate the Worker object directly. We have to operate all steps, and we can't delay the execution. With command mode, we can even use factories to create command classes, which makes it easier to use.

summary

The key of command mode is that it encapsulates the request / operation into a command object. These command objects are written in advance, and then give these commands to the implementer to complete the operation. Before the command is executed, you can revoke and add commands.

When I was learning command mode, I always thought about the difference between command mode and writing method? The direct write method also encapsulates the operation logic, but in this way, execution, undo and rollback cannot be delayed.

Added by Sportfishing on Fri, 15 Oct 2021 03:06:13 +0300