设计模式-行为型模式:命令模式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 设计模式-行为型模式:命令模式

1、简介

命令模式(Command Pattern)是一种行为型设计模式,它使得能够将请求封装成对象,并且让我们可以用不同的请求对客户端进行参数化,同时能够支持请求排队或记录请求日志,以及支持可撤销的操作。

2、组成部分

命令模式的核心结构包括以下四个部分:

  • Command(命令):声明了一个执行操作的接口。通常会包含一个 execute() 方法,当调用该方法时,接收者会执行相应的操作。
  • ConcreteCommand(具体命令):将一个接收者对象与一个动作(如一个方法调用)绑定起来。实现 execute() 方法,调用接收者相应的操作。
  • Receiver(接收者):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
  • Invoker(调用者):请求者,发起者。通过一个或多个命令对象来执行请求。它要求命令对象执行请求。

这些组件间的关系如下图所示:

3、优缺点

优点:

  1. 降低系统的耦合度:命令模式将请求和接收者对象解耦,使得系统更加灵活,并且可以方便地添加或删除命令,而不会对其他的对象产生影响。
  2. 容易扩展新的命令:命令模式使得添加新的命令非常容易,只需要实现新的命令对象,并将其加入到命令的集合中即可。
  3. 支持撤销和重做操作:命令模式可以记录所有执行过的命令,支持撤销和重做操作,这对于某些需要撤销操作的场景非常有用。
  4. 支持请求队列:命令模式可以将请求放入请求队列中,使得请求可以被延迟执行或者排队执行,这可以避免请求的发送者和接收者之间的时间耦合。

缺点:

  1. 可能会导致过多的具体命令类:每个具体命令都需要实现一个新的类,这可能会导致系统中存在大量的具体命令类,从而增加系统的复杂度。
  2. 可能会增加系统的代码复杂度:命令模式中需要定义多个类和接口,从而增加了系统的代码复杂度,这可能会增加开发成本和维护成本。

总之,命令模式是一种非常有用的设计模式,它可以使得系统更加灵活,并且可以方便地添加或删除命令,同时也支持撤销和重做操作。但是,在使用命令模式时,需要根据具体的情况权衡其优缺点,从而选择最适合的设计模式。

4、使用场景

命令模式是一种常用的设计模式,它适用于以下场景:

  1. 需要对请求进行排队或记录日志:命令模式可以将请求放入请求队列中,从而可以对请求进行排队或记录日志。例如,我们可以将用户的操作请求放入队列中,以便在系统繁忙时处理这些请求。
  2. 需要支持撤销和重做操作:命令模式可以记录所有执行过的命令,支持撤销和重做操作。例如,我们可以使用命令模式来实现文本编辑器中的撤销和重做功能。
  3. 需要支持事务操作:命令模式可以将一组相关的操作封装在一起,以支持事务操作。例如,我们可以使用命令模式来实现数据库中的事务处理。
  4. 需要支持日志记录和审计功能:命令模式可以记录每个命令的执行时间和执行者等信息,从而支持日志记录和审计功能。例如,我们可以使用命令模式来记录用户对系统的操作行为。
  5. 需要支持命令的撤销和重做操作:命令模式可以记录每个命令的执行状态,以支持撤销和重做操作。例如,在图形用户界面中,我们可以使用命令模式来实现对绘制命令的撤销和重做操作。
  6. 需要实现多级菜单或工具栏:命令模式可以将菜单或工具栏中的每个按钮都封装成一个命令,从而可以方便地添加或删除按钮,而不会对其他的按钮产生影响。

总之,命令模式可以解耦请求发送者和请求接收者之间的关系,使得系统更加灵活,同时也支持撤销和重做操作,日志记录和审计等功能。因此,命令模式在许多场景下都是非常有用的。

5、代码实现

下面是一个简单的例子来演示命令模式的使用场景。假设我们有一个遥控器,它能够控制各种设备,包括电视、音响等等。现在我们要实现一个遥控器,它具有打开电视、关闭电视、打开音响、关闭音响等功能。

首先,我们需要定义一个命令接口,其中包含了一个 execute() 方法:

1. public interface Command {
2. void execute();
3. }

然后,我们可以定义具体的命令类,如下所示:

1. public class TVOnCommand implements Command {
2. private TV tv;
3. 
4. public TVOnCommand(TV tv) {
5. this.tv = tv;
6.     }
7. 
8. @Override
9. public void execute() {
10.         tv.turnOn();
11.     }
12. }
1. public class TVOffCommand implements Command {
2. private TV tv;
3. 
4. public TVOffCommand(TV tv) {
5. this.tv = tv;
6.     }
7. 
8. @Override
9. public void execute() {
10.         tv.turnOff();
11.     }
12. }
1. public class StereoOnCommand implements Command {
2. private Stereo stereo;
3. 
4. public StereoOnCommand(Stereo stereo) {
5. this.stereo = stereo;
6.     }
7. 
8. @Override
9. public void execute() {
10.         stereo.turnOn();
11.     }
12. }
1. public class StereoOffCommand implements Command {
2. private Stereo stereo;
3. 
4. public StereoOffCommand(Stereo stereo) {
5. this.stereo = stereo;
6.     }
7. 
8. @Override
9. public void execute() {
10.         stereo.turnOff();
11.     }
12. }

其中,TVOnCommand、TVOffCommand、StereoOnCommand、StereoOffCommand 分别对应了打开电视、关闭电视、打开音响和关闭音响四种不同的命令。每个命令类都实现了 Command 接口,并且包含了一个接收者对象,用于执行实际的操作。

接下来,我们需要定义一个遥控器,它能够存储各种不同的命令,并且可以按下按钮来执行命令:

1. public class RemoteControl {
2. private Command[] onCommands;
3. private Command[] offCommands;
4. 
5. public RemoteControl() {
6.         onCommands = new Command[2];
7.         offCommands = new Command[2];
8.     }
9. 
10. public void setCommand(int slot, Command onCommand, Command offCommand) {
11.         onCommands[slot] = onCommand;
12.         offCommands[slot] = offCommand;
13.     }
14. 
15. public void onButtonWasPushed(int slot) {
16.         onCommands[slot].execute();
17.     }
18. 
19. public void offButtonWasPushed(int slot) {
20.         offCommands[slot].execute();
21.     }
22. }

在 RemoteControl 中,我们定义了两个数组,分别用于存储打开命令和关闭命令。setCommand() 方法用于设置命令,onButtonWasPushed() 和 offButtonWasPushed() 方法分别用于执行打开命令和关闭命令。

最后,我们需要定义接收者对象,也就是电视和音响:

1. public class TV {
2. public void turnOn() {
3.         System.out.println("TV is turned on");
4.     }
5. 
6. public void turnOff() {
7.         System.out.println("TV is turned off");
8.     }
9. }
10. 
11. public class Stereo {
12. public void turnOn() {
13.         System.out.println("Stereo is turned on");
14.     }
15. 
16. public void turnOff() {
17.         System.out.println("Stereo is turned off");
18.     }
19. }

现在,我们可以使用这些类来实现一个简单的遥控器,如下所示:

1. public static void main(String[] args) {
2. RemoteControl remote = new RemoteControl();
3. 
4. TV tv = new TV();
5. Stereo stereo = new Stereo();
6. 
7.     remote.setCommand(0, new TVOnCommand(tv), new TVOffCommand(tv));
8.     remote.setCommand(1, new StereoOnCommand(stereo), new StereoOffCommand(stereo));
9. 
10.     remote.onButtonWasPushed(0); // 打开电视
11.     remote.offButtonWasPushed(0); // 关闭电视
12.     remote.onButtonWasPushed(1); // 打开音响
13.     remote.offButtonWasPushed(1); // 关闭音响
14. }

输出结果为:

       TV is turned on

       TV is turned off

       Stereo is turned on

       Stereo is turned off

这个例子中,我们使用了命令模式,将请求封装成了对象,并且支持了请求排队、记录请求日志和支持可撤销的操作。这使得我们可以将遥控器的功能动态地配置,并且可以将不同的命令对象组合成新的组合命令,从而实现更多的功能。同时,由于每个命令对象都独立,所以可以方便地进行单元测试和模块化开发。

 

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
3月前
|
设计模式 存储 算法
Java设计模式-命令模式(16)
Java设计模式-命令模式(16)
|
4月前
|
设计模式 算法 Java
【十六】设计模式~~~行为型模式~~~策略模式(Java)
文章详细介绍了策略模式(Strategy Pattern),这是一种对象行为型模式,用于定义一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而变化,提高了系统的灵活性和可扩展性。通过电影院售票系统中不同类型用户的打折策略案例,展示了策略模式的动机、定义、结构、优点、缺点以及适用场景,并提供了Java代码实现和测试结果。
【十六】设计模式~~~行为型模式~~~策略模式(Java)
|
4月前
|
设计模式 网络协议 Java
【十五】设计模式~~~行为型模式~~~状态模式(Java)
文章详细介绍了状态模式(State Pattern),这是一种对象行为型模式,用于处理对象在其内部状态改变时的行为变化。文中通过案例分析,如银行账户状态管理和屏幕放大镜工具,展示了状态模式的应用场景和设计方法。文章阐述了状态模式的动机、定义、结构、优点、缺点以及适用情况,并提供了Java代码实现和测试结果。状态模式通过将对象的状态和行为封装在独立的状态类中,提高了系统的可扩展性和可维护性。
【十五】设计模式~~~行为型模式~~~状态模式(Java)
|
4月前
|
设计模式 存储 前端开发
【十四】设计模式~~~行为型模式~~~观察者模式(Java)
文章详细介绍了观察者模式(Observer Pattern),这是一种对象行为型模式,用于建立对象之间的一对多依赖关系。当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。文中通过交通信号灯与汽车的案例以及多人联机对战游戏的设计方案,阐述了观察者模式的动机和应用场景。接着,文章介绍了观察者模式的结构、角色、优点、缺点以及适用情况,并通过代码示例展示了如何在Java中实现观察者模式。此外,还探讨了观察者模式在MVC架构中的应用以及Java中对观察者模式的支持。
【十四】设计模式~~~行为型模式~~~观察者模式(Java)
|
4月前
|
设计模式 前端开发 Java
【十三】设计模式~~~行为型模式~~~中介者模式(Java)
文章详细介绍了中介者模式(Mediator Pattern),这是一种对象行为型模式,用于封装一系列对象的交互,降低系统耦合度,并简化对象之间的交互关系。通过案例分析、结构图、时序图和代码示例,文章展示了中介者模式的组成部分、实现方式和应用场景,并讨论了其优点、缺点和适用情况。
【十三】设计模式~~~行为型模式~~~中介者模式(Java)
|
4月前
|
设计模式 安全 Go
[设计模式]行为型模式-观察者模式
[设计模式]行为型模式-观察者模式
|
4月前
|
设计模式 存储 Java
【十二】设计模式~~~行为型模式~~~命令模式(Java)
文章详细介绍了命令模式(Command Pattern),这是一种对象行为型模式,用于将请求封装成对象,实现请求发送者与接收者的解耦,从而降低系统耦合度、提高灵活性,并支持命令的排队、记录、撤销和恢复操作。通过案例分析、结构图、时序图和代码示例,文章展示了命令模式的组成部分、实现方式和应用场景,并讨论了其优点、缺点和适用情况。
|
4月前
|
设计模式 算法 测试技术
[设计模式]行为型模式-策略模式
[设计模式]行为型模式-策略模式
|
5月前
|
设计模式 JavaScript API
js设计模式【详解】—— 命令模式
js设计模式【详解】—— 命令模式
48 6