Design mode - structural mode command mode

Smart Life project requirements

  1. We bought a set of smart appliances, including lights, fans, refrigerators and washing machines. We can control the work of these appliances as long as we install an app on our mobile phone.
  2. These smart appliances come from different manufacturers. We don't want to install an app for each kind of home appliance and control them separately. We hope that only one app can control all smart appliances.
  3. To realize the need for an app to control all smart appliances, each smart appliance manufacturer should provide a unified interface for app calls. At this time, you can consider using the command mode.
  4. Command mode decouples the action requester from the action performer object
  5. In our example, the requester of the action is a mobile app, and the executor of the action is a home appliance of each manufacturer

Basic introduction to command mode

  1. Command Pattern: in software design, we often need to send requests to some objects, but we don't know who the receiver of the request is or what the requested operation is. We just need to specify the specific receiver of the request when the program is running. At this time, we can use the Command Pattern for design
  2. The naming pattern makes the request sender and the request receiver eliminate the coupling between each other, makes the call relationship between objects more flexible and realizes decoupling.
  3. In the naming mode, a request is encapsulated as an object to represent different requests (i.e. naming) with different parameters. At the same time, the command mode also supports revocable operations.
  4. The general gives orders and the soldiers carry them out. There are several roles: General (the Command issuer), soldier (the specific executor of the Command), and Command (connecting general and soldier). Invoker is the caller (general), Receiver is the callee (soldier), and MyCommand is the Command. It implements the Command interface and holds the receiving object

Schematic class diagram of command mode

  • Description of schematic class diagrams - i.e. (roles and responsibilities of naming patterns)
  1. Invoker is the caller role
  2. Command: is a command role. All commands to be executed are here. They can be interfaces or abstract classes
  3. Receiver: the receiver role, which knows how to implement and execute a request related operation
  4. ConcreteCommand: bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute

Command mode to solve intelligent life project

Application example requirements

  1. Write the program and use the command mode to complete the previous smart home appliance project
  2. Train of thought analysis and illustration
  3. code implementation
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:01
     * @Description The receiver role knows how to implement and execute a request related operation
     **/
    public class LightReceiver {
    
        public void on(){
            System.out.println("The light is on");
        }
    
        public void off(){
            System.out.println("The lights are off");
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 18:58
     * @Description Command role - create command interface
     **/
    public interface Command {
        //Execute action (operation)
        public void execute();
    
        //Undo action
        public void undo();
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:00
     * @Description Bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute
     **/
    public class LightOffCommand implements Command {
        private LightReceiver light;
    
        public LightOffCommand(LightReceiver light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            //Call the recipient's method
            light.off();
        }
    
        @Override
        public void undo() {
            //Call the recipient's method
            light.on();
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 18:59
     * @Description Bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute
     **/
    public class LightOnCommand implements Command {
    
        private LightReceiver light;
    
        public LightOnCommand(LightReceiver light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            //Call the recipient's method
            light.on();
        }
    
        @Override
        public void undo() {
            //Call the recipient's method
            light.off();
        }
    
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:03
     * @Description Empty command (no command, i.e. empty execution: used to initialize the button) - it is helpful to simplify the operation and eliminate the judgment of empty
     * When an empty command is called, the object does nothing. In fact, this is also a design pattern, which can eliminate empty judgment
     **/
    public class NoCommand implements Command {
        @Override
        public void execute() {
    
        }
    
        @Override
        public void undo() {
    
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:01
     * @Description The receiver role knows how to implement and execute a request related operation
     **/
    public class TVReceiver {
    
        public void on(){
            System.out.println("The TV is on");
        }
    
        public void off(){
            System.out.println("The TV is off");
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:25
     * @Description Bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute
     **/
    public class TVOffCommand implements Command{
    
        private  TVReceiver tvReceiver;
    
        public TVOffCommand(TVReceiver tvReceiver) {
            this.tvReceiver = tvReceiver;
        }
    
        @Override
        public void execute() {
            tvReceiver.off();
        }
    
        @Override
        public void undo() {
            tvReceiver.on();
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:25
     * @Description Bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute
     **/
    public class TVOnCommand implements Command{
    
        private  TVReceiver tvReceiver;
    
        public TVOnCommand(TVReceiver tvReceiver) {
            this.tvReceiver = tvReceiver;
        }
    
        @Override
        public void execute() {
            tvReceiver.on();
        }
    
        @Override
        public void undo() {
            tvReceiver.off();
        }
    }
    
    package com.atguigu.command;
    
    /**
     * @Author panghl
     * @Date 2021/6/29 19:02
     * @Description Invoker Is the caller role
     **/
    public class RemoteController {
    
        //Command array of on button
        private Command[] onCommands;
        private Command[] offCommands;
    
        //Execute undo command
        private Command undoCommand;
    
        //Constructor to complete the initialization of the button
        public RemoteController() {
            onCommands = new Command[5];
            offCommands = new Command[5];
    
            for (int i = 0; i < 5; i++) {
                onCommands[i] = new NoCommand();
                offCommands[i] = new NoCommand();
            }
        }
        //Give our buttons the commands you need
        public void setCommand(int no,Command onCommand,Command offCommand){
            onCommands[no]= onCommand;
            offCommands[no]= offCommand;
        }
    
        //Press the on button
        public void onButtonWasPushed(int no){
            //Find the on button you pressed and call the corresponding method
            onCommands[no].execute();
            //Record this operation for cancellation
            undoCommand = onCommands[no];
        }
    
        //Press the close button
        public void offButtonWasPushed(int no){
            //Find the off button you pressed and call the corresponding method
            offCommands[no].execute();
            //Record this operation for cancellation
            undoCommand = offCommands[no];
        }
    
    
        //Press the undo button
        public void undoButtonWasPushed(){
            undoCommand.undo();
        }
    
    }
    

package com.atguigu.command;

/**
 * @Author panghl
 * @Date 2021/6/29 19:18
 * @Description TODO
 **/
public class Client {
    public static void main(String[] args) {
        //Use the command design mode to complete the operation of the electric lamp through the remote control

        //Create the object (recipient) of the light
        LightReceiver lightReceiver = new LightReceiver();

        //Create light related switch commands
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
        LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);

        //Need a remote control
        RemoteController remoteController = new RemoteController();

        //Set commands for our remote control, such as no = 0, which is the on and off operation of the electric light
        remoteController.setCommand(0,lightOnCommand,lightOffCommand);

        System.out.println("=======Press the on button of the lamp=============");

        remoteController.onButtonWasPushed(0);
        System.out.println("=======Press the light off button=============");
        remoteController.offButtonWasPushed(0);
        System.out.println("=======Press the lamp to cancel=============");
        remoteController.undoButtonWasPushed();


        System.out.println("television==============");
        TVReceiver tvReceiver = new TVReceiver();
        TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
        TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
        remoteController.setCommand(1,tvOnCommand,tvOffCommand);
        System.out.println("=======Press the TV on button=============");
        remoteController.onButtonWasPushed(1);
        System.out.println("=======Press the off button on the TV=============");
        remoteController.offButtonWasPushed(1);
        System.out.println("=======Press undo for TV=============");
        remoteController.undoButtonWasPushed();

    }
}

Source code analysis of the application of command pattern in Spring framework JdbcTemplate

  1. The JdbcTemplate of the Spring framework uses the command mode
  2. code analysis

  3. Description of pattern role analysis
  • StatementCallback interface, similar to command interface
  • Class querystatementcallback implements statementcallback < T >, sqlprovider, an anonymous internal class, implements the command interface and also acts as the command receiver
  • The command caller is JdbcTemplate, where execute (StatementCallback<T> action) method calls action.. Doinstatement method Different objects implementing statementcallback interface correspond to different doInStatemnt implementation logic
  • In addition, the subclass that implements the StatementCallback command interface also has QueryStatementCallback

Precautions and details of command mode

  1. Decouple the object that initiates the request from the object that executes the request. The object initiating the request is the caller. The caller can let the receiver work as long as he calls the execute() method of the command object, without knowing who the specific receiver object is and how to implement it. The command object will be responsible for letting the receiver perform the requested action, that is to say, the decoupling between "request initiator" and "request executor" is realized through the command object, The command object acts as a bridge.
  2. Easy to design a command queue. As long as the command object is queued, the command can be executed in multiple threads
  3. It is easy to undo and redo requests
  4. Insufficient command mode: some systems may have too many specific command classes, increasing the complexity of the system, which should be paid attention to when using
  5. Null command is also a design pattern, which saves us the operation of judging null. In the above example, if we don't use the empty command, we will judge it empty every time we press a key, which brings us some trouble in coding.
  6. Classic application scenario of command mode: a button on the interface is a command, simulating CMD (DOS command) order cancellation / recovery, and trigger feedback mechanism

Keywords: Design Pattern

Added by js_280 on Wed, 26 Jan 2022 20:32:38 +0200