设计模式——命令模式(遥控器与灯)

栏目: 后端 · 发布时间: 5年前

内容简介:本文主要对命令模式进行概述讲解,并使用使用遥控器与灯来讲述命令模式中调用者与接收者的关系。命令模式(英语:

本文主要对命令模式进行概述讲解,并使用使用遥控器与灯来讲述命令模式中调用者与接收者的关系。

设计模式——命令模式(遥控器与灯)

一、概述

命令模式(英语: Command pattern )是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被重复使用、撤销、撤销后重做。

这个是概念是来自维基百科,我觉得最容易理解,就是把命令封装成对象,使命令可以重复调用、撤销,降低了调用者和接受者的耦合,同时容易扩展出新的命令。

其他描述:

1.将“请求”封装成对象,以便使不同的请求、队列或日志来参数化其他对象,命令模式也支持可撤销操作。(Head First 设计模式)

2.命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。(Java与模式)

大家做适当参考,不理解可以先看看下面的源码!

二、结构

如图,这是命令模式的结构:

设计模式——命令模式(遥控器与灯)

以用遥控器开灯为例(Head First 设计模式例子)

  • Invoker:命令调用者,负责调用命令对象的请求—— 遥控器
  • Command:声明了一个具体命令类实现的接口—— 命令的接口
  • ConcreteCommand:具体命令,实现了Invoker和Receiver之间的解耦,通常持有接收者对象的饮用—— 开灯按钮执行的命令

  • Receiver:命令接收者,真正接收命令并执行动作的对象——

  • Client:客户端,创造具体的命令,并确定接收者

三、源代码

Receiver——二档亮度的灯

// 二档调节的灯,在这里作为接收者
public class Light {
    public static final String HIGH = "贼亮";

    public static final String MEDIUM = "有点亮";

    public static final String LOW = "快灭火了";

    public static final String OFF = "真的灭火了~";

    private String luminance;

    public Light() {
        this.luminance = OFF;
    }

    public void off() {
        System.out.println("灯关闭了");
        this.luminance = OFF;
    }

    public void high() {
        System.out.println("贼亮");
        this.luminance = HIGH;
    }

    public void medium() {
        System.out.println("挺亮地!");
        this.luminance = MEDIUM;
    }

    public void low() {
        System.out.println("快灭火了");
        this.luminance = LOW;
    }
    
    public String getLuminance(){
        return this.luminance;
    }
}

Command——做个命令接口,带撤销功能

public interface Command {
    void excute();
    void undo();
}

LightHighCommand——高光命令

public class LightHighCommand implements Command {
    private Light light;
    private String preLuminance;
    @Override
    public void excute() {
        // 备份上一个命令,撤销使用
        preLuminance = light.getLuminance();
        light.high();
    }

    @Override
    public void undo() {
        if (Light.HIGH.equals(preLuminance)){
            light.high();
        }else if(Light.MEDIUM.equals(preLuminance) ){
            light.medium();
        }else if (Light.LOW.equals(preLuminance)){
            light.low();
        }else if (Light.OFF.equals(preLuminance)){
            light.off();
        }
    }

    public LightHighCommand(Light light) {
        this.light = light;
    }
    // 智能遥控器按键功能可以控制多个灯
    // 如果控制令一个接收者,可以传入,不用新建命令
    public void setLight(Light light) {
        this.light = light;
    }
}

LightOffCommand——关灯命令

public class LightOffCommand implements Command {
    private Light light;
    private String preLuminance;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void excute() {
        preLuminance = light.getLuminance();
        light.off();
    }

    @Override
        public void undo() {
            if (Light.HIGH.equals(preLuminance)){
                light.high();
            }else if(Light.MEDIUM.equals(preLuminance) ){
                light.medium();
            }else if (Light.LOW.equals(preLuminance)){
                light.low();
            }else if (Light.OFF.equals(preLuminance)){
                light.off();
            }
        }
    
    public void setLight(Light light) {
        this.light = light;
    }
}

Invoker——遥控器

public class RemoteControl {
    private Command off;
    private Command high;
    private Command medium;
    private Command low;
    private Command preCommand;

    public void setOff(Command off) {
        this.off = off;

    }

    public void setHigh(Command high) {
        this.high = high;
    }

    public void setMedium(Command medium) {
        this.medium = medium;
    }

    public void setLow(Command low) {
        this.low = low;

    }

    public void lightOff() {
        off.excute();
        preCommand = off;
    }

    public void lightHigh() {
        high.excute();
        preCommand = high;

    }

    public void lightMedium() {
        medium.excute();
        preCommand = medium;

    }

    public void lightLow() {
        low.excute();
        preCommand = low;
    }

    public void undo() {
        if (preCommand == null) {
            System.out.println("无法撤销");
        } else {
            preCommand.undo();
        }
    }
}

Client——客户端

public class Client {
    public static void main(String[] args) {
        // 创建接收者
        Light light = new Light();
        // 创建命令
        Command lightHighCommand = new LightHighCommand(light);
        Command lightOffCommand = new LightOffCommand(light);
        // 创建调用者
        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setHigh(lightHighCommand);
        remoteControl.setOff(lightOffCommand);
        // 调用
        remoteControl.lightHigh();
        remoteControl.lightOff();
        remoteControl.undo();
    }
}

————————>结果
贼亮
灯关闭了
贼亮

以上就是一个带撤回功能的命令模式,其中:

如果想实现 多步撤回 ,可以考虑把调用者中的preCommand换成stack;

如果想实现 组合命令 ,可以重新创建一个 宏命令 ,如下

public class MacroCommand implements Command {
    private Command[] commands;

    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }

    @Override
    public void excute() {
        for (Command command : commands) {
            command.excute();
        }
    }

    @Override
    public void undo() {
        for (Command command : commands) {
            command.undo();
        }
    }
}

你可以用这个命令实现任何形式的命令组合,甚至如果你觉得你的遥控器可以控制空调,控制电源,控制电饭锅,你甚至可以把这些命令组合进来~

四、命令模式的优缺点

优点

  • 解耦合:将命令调用者和命令执行者通过命令进行解耦,命令调用者不关心由谁来执行命令,只要命令执行就可以

  • 更动态的控制:请求被封装成对象后,可以轻易的参数化、队列化、日志化,使系统更加灵活。

  • 更容易的命令组合 :有了宏命令后,可以任意的对命令进行组合
  • 更好扩展性 :可以轻易的添加新的命令,并不会影响到其他的命令

缺点

  • 命令过多时,会创建了过多的命令类,不方便进行管理

五、总结

本文对命令模式作了简单的介绍,命令模式只要明白调用者如何通过命令与接收者交互,就比较好理解。在实际应用中,命令模式可以用在并行处理、事务行为、线程池等地方。例如传统的线程池就有addTask()方法将命令加入到等待被执行的队列中,允许多线程执行实现 java.lang.Runnable 的命令,尽管线程池本身对具体的任务毫无认知。

本文首发于cdream个人博客

欢迎转载,转载请注明出处!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mission Python

Mission Python

Sean McManus / No Starch Press / 2018-9-18 / GBP 24.99

Launch into coding with Mission Python, a space-themed guide to building a complete computer game in Python. You'll learn programming fundamentals like loops, strings, and lists as you build Escape!, ......一起来看看 《Mission Python》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具