程序员必知!命令模式的实战应用与案例分析

程序员必知!命令模式的实战应用与案例分析 - 程序员古德

命令模式是一种行为设计模式,它将请求封装为对象以实现客户端参数化、请求排队、日志记录及撤销操作,旨在解耦调用者与操作实现者,以智能家居为例,用户通过界面发送命令对象,设备作为接收者执行相应操作,无需用户了解具体执行方式,从而增强了系统的灵活性和可扩展性。

定义

程序员必知!命令模式的实战应用与案例分析 - 程序员古德

命令模式是一种行为设计模式,它允许将一个请求封装为一个对象,从而可用不同的请求把客户端参数化,对请求排队或记录请求日志,以及支持可撤销的操作,主要目的是将调用操作的对象与知道如何实现该操作的对象解耦。

举一个业务中的例子来说明命令模式:假如有一个智能家居系统,其中有各种设备如灯光、空调、窗帘等,用户可以通过手机应用、语音助手或墙壁开关来控制这些设备,在这个场景中,命令模式可以很好地应用,在命令模式中有如下几个角色和分工:

  1. 命令对象:每个设备操作(如“打开灯光”、“关闭空调”)都可以封装为一个命令对象,这个命令对象包含了执行该操作所需的所有信息,包括目标设备、操作类型等。
  2. 调用者:用户或用户通过的界面(如手机应用)是调用者,他们不知道具体如何执行某个操作,但他们可以创建和发送命令对象。
  3. 接收者:实际执行操作的设备(如灯光设备、空调设备)是接收者,它们知道如何响应特定的命令。
  4. 撤销操作:命令模式还支持撤销操作,例如,如果用户误操作打开了灯光,他们可以发送一个“关闭灯光”的命令来撤销之前的操作。

这个例子中,用户(调用者)只需要发送命令,而不需要知道如何执行这些命令,设备(接收者)则负责根据接收到的命令执行相应的操作,这使得系统更加灵活和可扩展。

代码案例

程序员必知!命令模式的实战应用与案例分析 - 程序员古德

日常开发中,未使用命令模式时,代码通常会直接将调用者和接收者紧密耦合在一起,下面是一个简单的反例,展示了未使用命令模式时如何实现一个智能家居系统中的灯光控制功能。首先,定义一个Light类作为接收者,它负责执行打开和关闭灯光的操作,如下代码:

// 灯光类,作为接收者  
public class Light {  
    private boolean isOn;  
  
    public Light() {  
        this.isOn = false;  
    }  
  
    // 打开灯光  
    public void turnOn() {  
        this.isOn = true;  
        System.out.println("Light is on.");  
    }  
  
    // 关闭灯光  
    public void turnOff() {  
        this.isOn = false;  
        System.out.println("Light is off.");  
    }  
  
    // 检查灯光状态  
    public boolean isOn() {  
        return isOn;  
    }  
}

接下来,定义一个SmartHomeController类作为调用者,在这个类中,直接调用了Light对象的方法,如下代码:

// 智能家居控制器类,作为调用者  
public class SmartHomeController {  
    private Light light;  
  
    public SmartHomeController(Light light) {  
        this.light = light;  
    }  
  
    // 控制灯光打开  
    public void controlLightOn() {  
        light.turnOn();  
    }  
  
    // 控制灯光关闭  
    public void controlLightOff() {  
        light.turnOff();  
    }  
}

最后,在client代码中使用SmartHomeController来控制灯光的打开和关闭,如下代码:

// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        // 创建灯光对象  
        Light light = new Light();  
  
        // 创建智能家居控制器对象,并将灯光对象传递给它  
        SmartHomeController controller = new SmartHomeController(light);  
  
        // 控制灯光打开  
        controller.controlLightOn();  
  
        // 控制灯光关闭  
        controller.controlLightOff();  
  
        // 如果需要添加撤销操作或者记录操作日志,这种直接调用的方式将会变得复杂  
    }  
}

输出结果:

Light is on.  
Light is off.

在这个反例中,SmartHomeController直接调用了Light对象的方法,这意味着如果需要添加额外的功能,比如记录操作日志,则需要在SmartHomeController中添加相应的逻辑,这会增加代码的复杂性,并且违反了开闭原则(对扩展开放,对修改关闭),此外,如果需要替换灯光控制的实现,比如使用远程服务器来控制灯光,也需要修改SmartHomeController的代码。

下面是一个使用命令模式的正例代码,展示了如何实现一个智能家居系统中的灯光控制功能,当使用命令模式时,可以将请求封装为对象,并在调用者和接收者之间引入一个间接层,首先,定义一个Light类作为接收者,它负责执行打开和关闭灯光的操作,如下代码:

// 灯光类,作为接收者  
public class Light {  
    private boolean isOn;  
  
    public Light() {  
        this.isOn = false;  
    }  
  
    // 打开灯光  
    public void turnOn() {  
        this.isOn = true;  
        System.out.println("Light is on.");  
    }  
  
    // 关闭灯光  
    public void turnOff() {  
        this.isOn = false;  
        System.out.println("Light is off.");  
    }  
  
    // 检查灯光状态(此例中未使用,仅为完整性)  
    public boolean isOn() {  
        return isOn;  
    }  
}

接下来,定义命令接口和它的实现类,如下代码:

// 命令接口  
public interface Command {  
    void execute();  
    void undo();  
}  
  
// 打开灯光命令实现  
public class TurnOnLightCommand implements Command {  
    private Light light;  
  
    public TurnOnLightCommand(Light light) {  
        this.light = light;  
    }  
  
    @Override  
    public void execute() {  
        light.turnOn();  
    }  
  
    @Override  
    public void undo() {  
        light.turnOff();  
    }  
}  
  
// 关闭灯光命令实现  
public class TurnOffLightCommand implements Command {  
    private Light light;  
  
    public TurnOffLightCommand(Light light) {  
        this.light = light;  
    }  
  
    @Override  
    public void execute() {  
        light.turnOff();  
    }  
  
    @Override  
    public void undo() {  
        light.turnOn();  
    }  
}

然后,定义一个调用者类SmartHomeController,它不直接调用接收者,而是使用命令对象来执行操作,如下代码:

// 智能家居控制器类,作为调用者  
import java.util.Stack;  
  
public class SmartHomeController {  
    private Stack<Command> commandStack = new Stack<>();  
  
    // 执行命令,并将命令压入栈中以支持撤销  
    public void executeCommand(Command command) {  
        command.execute();  
        commandStack.push(command);  
    }  
  
    // 撤销上一个命令  
    public void undoLastCommand() {  
        if (!commandStack.isEmpty()) {  
            Command lastCommand = commandStack.pop();  
            lastCommand.undo();  
        }  
    }  
}

最后,在客户端代码中使用SmartHomeController来控制灯光的打开和关闭,并展示撤销功能:

// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        // 创建灯光对象  
        Light light = new Light();  
  
        // 创建智能家居控制器对象  
        SmartHomeController controller = new SmartHomeController();  
  
        // 创建并打开灯光命令  
        Command turnOnCommand = new TurnOnLightCommand(light);  
        controller.executeCommand(turnOnCommand);  
  
        // 创建并关闭灯光命令  
        Command turnOffCommand = new TurnOffLightCommand(light);  
        controller.executeCommand(turnOffCommand);  
  
        // 撤销上一个命令(关闭灯光),灯光应该会再次打开  
        controller.undoLastCommand();  
    }  
}

输出结果:

Light is on.  
Light is off.  
Light is on.

在这个例子中,SmartHomeController不再直接调用Light对象的方法,而是通过Command接口间接地执行操作,这种间接层允许在不修改调用者和接收者的情况下添加新功能,比如日志记录。此外,由于调用者和接收者之间的解耦,可以轻松地替换灯光控制的实现,比如使用远程服务器来控制灯光,而不需要修改SmartHomeController的代码。

核心总结

程序员必知!命令模式的实战应用与案例分析 - 程序员古德

命令模式,作为行为设计模式的一种,其核心思想在于将请求或操作封装成对象,这种封装不仅让请求本身变得更加具体和可管理,更重要的是,它实现了请求发送者与请求接收者之间的解耦。在传统的程序设计中,请求的发送者往往直接调用接收者的方法,这种方式虽然简单直接,但会导致发送者和接收者之间紧密耦合,不利于代码的维护和扩展。

在复杂的业务场景中,特别是当存在多个调用者和接收者,并且这些组件之间需要解耦时,命令模式就显得尤为有用。通过命令模式可以将调用者和接收者完全分离,调用者不再直接调用接收者的方法,而是通过一个中间的命令对象来间接地发出请求,这个命令对象封装了接收者的方法调用和相关的参数,它可以在调用者和接收者之间传递,并在适当的时候由调用者执行。

其它思考

命令模式在一些设计模式中可能会与其他模式产生混淆,尤其是与策略模式和状态模式,如下:

  1. 策略模式,策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换,策略模式关注的是算法的替换问题,允许在运行时选择使用哪个算法,而命令模式则更关注于请求的封装、排队和撤销等操作,尽管两者都涉及到了行为的封装和替换,但它们的意图和使用场景是不同的。
  2. 状态模式,状态模式允许对象在内部状态改变时改变其行为,看起来好像修改了其类,状态模式与命令模式在处理对象行为方面有一定的相似性,但它们解决的问题不同,状态模式关注的是对象状态变化时的行为改变,而命令模式则关注于将请求封装为对象以实现解耦和撤销等操作。

总结:策略模式关注算法的替换,状态模式关注状态变化时的行为改变,而命令模式关注请求的封装、排队和撤销等操作。

完!

关注我,每天学习互联网编程技术 - 程序员古德

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《程序员必知的硬核知识大全》是一本面向程序员的综合性知识手册,涵盖了各个领域的关键知识点,旨在帮助程序员提升技术水平和解决实际问题。该书以PDF格式出版,便于读者在电脑、手机等设备上随时查阅。 该书内容包括以下几个方面的硬核知识: 1. 编程语言知识:介绍了主流的编程语言,如Java、C++、Python等,包括语法、数据结构、算法等方面的内容。 2. 操作系统和计算机原理:详细介绍了操作系统的基本原理和常见问题解决方法,以及计算机组成原理和计算机网络等相关知识。 3. 数据库和存储知识:讲解了数据库设计和管理的基本原理,介绍了关系型数据库如MySQL和非关系型数据库如MongoDB等的使用方法和优化技巧。 4. 网站和网络开发知识:包括Web开发的基本原理、前后端开发技术、网络安全和性能优化等方面的内容。 5. 软件工程和开发方法论:介绍了软件工程的基本概念和常用开发方法,包括敏捷开发、测试驱动开发和持续集成等。 6. 设计模式和架构知识:详细介绍了常用的设计模式和软件架构,帮助程序员设计可维护、可扩展和高效的软件系统。 除了以上几个方面的内容,该书还涵盖了其他与程序员工作密切相关的技术和知识,如版本控制、软件部署、性能调优等。《程序员必知的硬核知识大全》适合本科或者有一定编程经验的程序员阅读,对于提高技术实力和职业发展都有很大帮助。 ### 回答2: "程序员必知的硬核知识大全 pdf"是一份提供程序员必备知识的电子书,PDF格式可以方便地在各种设备上阅读。这本书包含了各个方面的硬核知识,帮助程序员提高技术能力和解决问题的能力。 这本电子书的内容包括了数据结构和算法,编程语言,操作系统,网络通信,数据库管理等各方面的知识。对于程序员而言,这些都是非常重要的基础知识,能够帮助他们理解和设计高效的程序。 在数据结构和算法部分,程序员将学习到各种基础的数据结构,如数组、链表、栈和队列,以及常见的算法,如排序和搜索算法。这些知识对于程序的效率和性能优化至关重要。 编程语言部分将介绍多种编程语言,如C、C++、Java和Python等。这些语言在不同的领域有各自的优点和适用范围,程序员需要了解它们的特点和使用方法,以便在开发项目时选择合适的语言。 操作系统部分将深入讲解操作系统的原理和设计。程序员将了解到进程管理、内存管理、文件系统等重要概念,这些对于编写具有高可靠性和高性能的程序至关重要。 网络通信部分将介绍计算机网络的基本原理和常见的协议,如TCP/IP和HTTP等。程序员需要理解网络通信的基础知识,以便与其他系统进行数据交换和通信。 数据库管理部分将详细介绍关系型数据库和非关系型数据库的原理和使用方法。程序员需要了解数据库的设计和优化,以提高数据的存储和检索效率。 总之,这本电子书涵盖了程序员必备的硬核知识,对于提高他们的技术能力和解决问题的能力非常有帮助。 ### 回答3: 《程序员必知的硬核知识大全》是一本汇集了程序员必备的核心知识的书籍,可以帮助程序员提升自己的技术水平。这本书涵盖了计算机科学的各个领域和重要概念,包括数据结构与算法、操作系统、编程语言、网络通信、数据库、Web开发、软件工程等。 在数据结构与算法部分,书介绍了常用的数据结构如链表、栈、队列以及各种排序和搜索算法,帮助程序员理解和应用这些经典的算法。在操作系统方面,书讲解了进程、线程、内存管理、文件系统等重要概念,帮助程序员深入了解计算机系统的工作原理。 在编程语言方面,书列举了多种编程语言的特性和应用场景,如C++、Java、Python等,有助于程序员选择适合自己的编程语言并掌握其特性。在网络通信部分,书介绍了TCP/IP协议、HTTP协议等重要的网络通信协议和技术,帮助程序员理解网络通信的基本原理。 此外,书还介绍了数据库的相关知识,包括关系数据库、SQL语言、数据备份与恢复等内容,有助于程序员设计和管理数据库。在Web开发方面,书介绍了前端开发、后端开发、服务器部署等关键技术,帮助程序员构建高效、安全的Web应用程序。 最后,在软件工程方面,书讲解了软件开发的生命周期、需求分析、设计模式、测试和持续集成等内容,有助于程序员理解和掌握软件开发过程的重要环节。 总的来说,这本《程序员必知的硬核知识大全》提供了一站式的学习资料,涵盖了程序员必备的核心知识,可以帮助程序员系统地学习和应用这些知识,提升自己的技术能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员古德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值