Design Patterns - command mode (Command)

No. JavaStorm public attention for more growth.

It takes about 6 minutes to read. Collection after reading suggestions.
The command mode operation or a request to a packaged object. Command mode allows the system to use a different request of the client parameters, the request queue or log requests, and can provide an undo command recovery.
GitHub Address: https://github.com/UniqueDong/zero-design-stu the package under the code headfirst.

Outline

Command mode of the command is encapsulated. Command mode to issue a command responsibility and the responsibility of executing commands separated, assigned to different objects.

Each command is an operation: the requesting party requesting perform a required operation; receiving party receives the request, and performs an operation. Mode allows one command and one of the received requests independent open, so that the requesting party does not have to know the interface of one of receiving the request, not to know how the request was received, and whether the operation is performed, when it was performed, and how the It is executed.

Command allows one party requests and receive requests can be evolved independently, so as to have the following advantages:

(1) command mode so that the new command be easily added to the system.

(2) allows one to decide whether the received request is a request to be rejected.

(3) can be more easily designed a command queue.

(4) can be easily realized to undo and redo request.

(5) In case of need, it can be more easily command logged.
Class Diagram

Roles

  • Client (Client) role: to create a ConcreteCommand, and set its recipient.
  • Command (Command) Role: declare an interface to all commands. Call the command object execute method can allow the recipient to perform related actions, the interface also has a co-worker undo () method withdrawn.
  • Specific order (ConcreteCommand) Role: weak coupling between the receiver and defines a behavior; implement execute () method, is responsible for operation of the corresponding call recipient. execute () method is usually called the execution method. The caller need only execute method can request, and then one or more actions invoked by the recipient ConcreteCommand.
  • The caller (Invoker) roles: the caller to hold a command object execute method provides a method call trigger command object, the command will be executed.
  • Receiver (Receiver) Role: responsible for implementing and executing a request. Any class can be a receiver, the method of execution of the request and called the action method.

Implementation process

  1. The client creates a command object.
  2. SetCommand client calls the method on the caller object.
  3. In the next appropriate point in time, the caller calls the execute method of the command object.
  4. Command entrusted to the corresponding recipients performed by the caller. mission accomplished.

Scene simulation

A versatile programmable remote control 6 slots (each of which may specify a different home appliance), for controlling home appliances (TV, air conditioners, refrigerators, stereo). Each slot has a corresponding [On] and [OFF] button. It also has a whole a key withdrawn button. Demand is the withdrawal of the case, such as the lamp is off, then press the button to turn on lights were opened. Now if the Undo button is pressed, then the action will be reversed. Here, the lights will be turned off.
remote control
Appliances connected to the corresponding slot, the corresponding instruction is a switch. Each appliance corresponding to two instructions, namely, [open] and [OFF] button.

Many appliances have on () and off () method, in addition to a number of setVolumn (), setTV (), setTemperature () method.
We can not write if slot1 == Light then light.on () .

Code

Command Recipient Roles

First, we have a lot of appliances. In fact, they are the audience for different commands execution.

  • light
package com.zero.headfirst.command.receiver;

public class Light {
    public void on() {
        System.out.println("打开电灯。");
    }
    public void off() {
        System.out.println("关灯。");
    }
}

  • sound
package com.zero.headfirst.command.receiver;

public class Stereo {
    public void on() {
        System.out.println("打开音响");
    }

    public void off() {
        System.out.println("关闭音响");
    }

    public void setCD() {
        System.out.println("放入CD");
    }

    public void setVolume() {
        System.out.println("音响音量设置为20");
    }
}

Command role

First of all command object that implements this interface, respectively, command execution and withdrawal

package com.zero.headfirst.command;

/**
 * 命令(Command)角色
 */
public interface Command {
    /**
     * 命令执行
     */
    void execute();

    /**
     * 命令撤销
     */
    void undo();
}

Specific command role

  • Defined command lights to achieve execute. Command receiver holds a reference light, so that when the caller calls the delegate to execute the corresponding operation lamp lights performed.
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Light;

public class LightOnCommand implements Command {

    /**
     * 持有接受者实例,以便当命令execute执行的时候由接受者执行开灯
     */
    private Light light;

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }

    /**
     * 设置命令的接受者
     * @param light
     */
    public void setLight(Light light) {
        this.light = light;
    }
}

  • Defined command lights
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Light;

public class LightOffCommand implements Command {

    /**
     * 持有接受者实例,以便当命令execute执行的时候由接受者执行
     */
    private Light light;

    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }

    public void setLight(Light light) {
        this.light = light;
    }
}

  • Open sound defined command
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Stereo;

/**
 * 音响开指令
 */
public class StereoOnCommand implements Command {

    private Stereo stereo;

    @Override
    public void execute() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume();
    }

    @Override
    public void undo() {
        stereo.off();
    }

    public void setStereo(Stereo stereo) {
        this.stereo = stereo;
    }
}

  • Close command defined sound
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Stereo;

public class StereoOffCommand implements Command {

    private Stereo stereo;

    public void setStereo(Stereo stereo) {
        this.stereo = stereo;
    }

    @Override
    public void execute() {
        stereo.off();
    }

    @Override
    public void undo() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume();
    }
}

The remaining Turn on the TV, turn off the TV, turn on air-conditioning, close the air of not one to write. The template is the same routine. Now specific code can GitHub address: https://github.com/UniqueDong/zero-design-stu the package under the code headfirst.

The caller role

In fact, our remote control.

package com.zero.headfirst.command;

import com.zero.headfirst.command.impl.NoCommand;

import java.util.Arrays;

/**
 * 调用者:遥控器
 */
public class RemoteControl {
    /**
     * 一共4个家电插槽,每个插槽有 开与关命令。
     */
    private Command[] onCommands;
    private Command[] offCommands;

    //用来保存前一个命令,用来实现撤销功能
    private Command undoCommand;

    /**
     * 通过构造器初始化开关数组
     */
    public RemoteControl() {
        onCommands = new Command[4];
        offCommands = new Command[4];
        //初始化所有插槽为空指令
        Command noCommand = new NoCommand();
        for (int i = 0; i < 4; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        //一开始没有所谓的前一个命令,所以默认无指令
        undoCommand = noCommand;
    }

    /**
     * 设置指定插槽对应的按钮指令
     * @param slot 插槽位置
     * @param onCommand 开指令
     * @param offCaommand 关指令
     */
    public void setCommand(int slot,Command onCommand, Command offCaommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCaommand;
    }

    /**
     * 模拟按下指定插槽对应的【开】按键
     */
    public void pressOnButton(int slot) {
        onCommands[slot].execute();
        //将当前指令记录下来,用于在撤销的时候能执行命令对应的 undo 方法从而实现撤销功能
        undoCommand = onCommands[slot];
    }

    /**
     * 模拟按下指定插槽对应的【关】按键
     */
    public void pressOffButton(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }

    /**
     * 撤销功能
     */
    public void pressUndoButton() {
        undoCommand.undo();
    }

    @Override
    public String toString() {
        return "RemoteControl{" +
                "onCommands=" + Arrays.toString(onCommands) +
                ", offCommands=" + Arrays.toString(offCommands) +
                '}';
    }
}

Client role

Obtaining remote control, and to get the lights, air-conditioning command receiver. [Create the corresponding opening respectively], [off] command.
Link to the corresponding slot. When the button is pressed the trigger of the specified instructions.

package com.zero.headfirst.command;

import com.zero.headfirst.command.impl.*;
import com.zero.headfirst.command.receiver.AirConditioning;
import com.zero.headfirst.command.receiver.Light;
import com.zero.headfirst.command.receiver.Stereo;
import com.zero.headfirst.command.receiver.TV;

/**
 * 客户端角色
 */
public class CommandClient {
    public static void main(String[] args) {
        //创建一个遥控器-调用者角色
        RemoteControl remoteControl = new RemoteControl();
        //1. 创建电灯-接受者角色
        Light light = new Light();
        //创建开灯、关灯命令-命令具体角色
        LightOnCommand lightOnCommand = new LightOnCommand();
        lightOnCommand.setLight(light);
        LightOffCommand lightOffCommand = new LightOffCommand();
        lightOffCommand.setLight(light);

        //调用者设置电灯插槽以及对应的开关按键指令-调用者角色
        remoteControl.setCommand(0, lightOnCommand, lightOffCommand);

        // 2. 设置音响插槽与对应按键指令
        Stereo stereo = new Stereo();
        StereoOnCommand stereoOnCommand = new StereoOnCommand();
        stereoOnCommand.setStereo(stereo);
        StereoOffCommand stereoOffCommand = new StereoOffCommand();
        stereoOffCommand.setStereo(stereo);

        remoteControl.setCommand(1, stereoOnCommand, stereoOffCommand);

        //3. 空调
        AirConditioning airConditioning = new AirConditioning();
        AirConditioningOnCommand airConditioningOnCommand = new AirConditioningOnCommand();
        airConditioningOnCommand.setAirConditioning(airConditioning);
        AirConditioningOffCommand airConditioningOffCommand = new AirConditioningOffCommand();
        airConditioningOffCommand.setAirConditioning(airConditioning);

        remoteControl.setCommand(2, airConditioningOnCommand, airConditioningOffCommand);

        //4. 电视
        TV tv = new TV();
        TVOnCommand tvOnCommand = new TVOnCommand();
        tvOnCommand.setTv(tv);
        TVOffCommand tvOffCommand = new TVOffCommand();
        tvOffCommand.setTv(tv);

        remoteControl.setCommand(3, tvOnCommand, tvOffCommand);

        //模拟按键
        System.out.println("-------码农回家了,使用遥控开启电灯、音响、空调、电视----");
        remoteControl.pressOnButton(0);
        remoteControl.pressOnButton(1);
        remoteControl.pressOnButton(2);
        remoteControl.pressOnButton(3);

        System.out.println("------码农睡觉了,使用遥控关闭电灯、音响、电视。不关空调--------");
        remoteControl.pressOffButton(0);
        remoteControl.pressOffButton(1);
        remoteControl.pressOffButton(3);

        System.out.println("----撤销测试,先打开电灯。再关闭电灯。然后按撤销----");
        remoteControl.pressOnButton(0);
        remoteControl.pressOffButton(0);
        //一键撤销
        remoteControl.pressUndoButton();
    }
}

Test Results

-------码农回家了,使用遥控开启电灯、音响、空调、电视----
打开电灯。
打开音响
放入CD
音响音量设置为20
打开空调
空调温度设置28°
打开电视
设置频道为宇宙电视台
电视音量设置为20
------码农睡觉了,使用遥控关闭电灯、音响、电视。不关空调--------
关灯。
关闭音响
关闭电视
----撤销测试,先打开电灯。再关闭电灯。然后按撤销----
打开电灯。
关灯。
打开电灯。

to sum up

scenes to be used:

  1. Work queue: one end of the addition instruction, the object is achieved as long as the command mode can be put in the queue. The other end is the thread. Thread proceeds following work: a command from the queue, and then execute method is called, the call is discarded after the command, and then continue to remove a command.
  2. Thread Pool.

No more public attention JavaStorm mode

Here Insert Picture Description

Published 28 original articles · won praise 2 · Views 1470

Guess you like

Origin blog.csdn.net/qq_14855971/article/details/92098100