【HeadFirst系列之HeadFirst计划模式】第7天之命令模式:封装请求,轻松实 ...

打印 上一主题 下一主题

主题 967|帖子 967|积分 2901

命令模式:封装请求,轻松实现解耦!

大家好!本日我们来聊聊计划模式中的命令模式(Command Pattern)。如果你曾经需要将请求封装成对象,大概盼望实现请求的取消、重做等功能,那么命令模式就是你的不二之选!本文基于《Head First 计划模式》的命令模式章节,通过生动的故事和 Java 代码示例,带你轻松掌握命令模式的英华。


1. 命令模式是什么?

命令模式是一种举动型计划模式,它将请求封装成对象,从而使你可以用不同的请求对客户进行参数化,并支持请求的列队、记录日志、取消等操纵。命令模式的核心头脑是解耦请求的发送者和接收者,使得系统更加灵活和可扩展。
实用场景



  • 需要将请求封装成对象,以便在不同的上下文中利用。
  • 需要支持请求的取消、重做、列队等功能。
  • 需要解耦请求的发送者和接收者。

2. 命令模式的实现

故事背景

小明开辟了一个智能家居系统,系统中有一个遥控器(RemoteControl)类,用于控制各种家电装备,比如(Light)、风扇(Fan)等。每个装备都有不同的操纵,比如打开、关闭、调节亮度等。
问题出现

如果直接在遥控器中调用装备的方法,会导致遥控器和装备之间的耦合度过高。此外,如果需要支持取消操纵,代码会变得非常复杂。
解决方案:命令模式

小明决定利用命令模式,将每个操纵封装成一个命令对象,从而解耦遥控器和装备。
代码实现

1. 界说命令接口

  1. // 命令接口
  2. interface Command {
  3.     void execute();
  4.     void undo();
  5. }
复制代码
2. 实现具体命令

  1. // 具体命令:打开灯
  2. class LightOnCommand implements Command {
  3.     private Light light;
  4.     public LightOnCommand(Light light) {
  5.         this.light = light;
  6.     }
  7.     @Override
  8.     public void execute() {
  9.         light.on();
  10.     }
  11.     @Override
  12.     public void undo() {
  13.         light.off();
  14.     }
  15. }
  16. // 具体命令:关闭灯
  17. class LightOffCommand implements Command {
  18.     private Light light;
  19.     public LightOffCommand(Light light) {
  20.         this.light = light;
  21.     }
  22.     @Override
  23.     public void execute() {
  24.         light.off();
  25.     }
  26.     @Override
  27.     public void undo() {
  28.         light.on();
  29.     }
  30. }
  31. // 具体命令:打开风扇
  32. class FanOnCommand implements Command {
  33.     private Fan fan;
  34.     public FanOnCommand(Fan fan) {
  35.         this.fan = fan;
  36.     }
  37.     @Override
  38.     public void execute() {
  39.         fan.on();
  40.     }
  41.     @Override
  42.     public void undo() {
  43.         fan.off();
  44.     }
  45. }
  46. // 具体命令:关闭风扇
  47. class FanOffCommand implements Command {
  48.     private Fan fan;
  49.     public FanOffCommand(Fan fan) {
  50.         this.fan = fan;
  51.     }
  52.     @Override
  53.     public void execute() {
  54.         fan.off();
  55.     }
  56.     @Override
  57.     public void undo() {
  58.         fan.on();
  59.     }
  60. }
复制代码
3. 界说装备类

  1. // 灯类
  2. class Light {
  3.     public void on() {
  4.         System.out.println("Light is on");
  5.     }
  6.     public void off() {
  7.         System.out.println("Light is off");
  8.     }
  9. }
  10. // 风扇类
  11. class Fan {
  12.     public void on() {
  13.         System.out.println("Fan is on");
  14.     }
  15.     public void off() {
  16.         System.out.println("Fan is off");
  17.     }
  18. }
复制代码
4. 实现遥控器

  1. // 遥控器类
  2. class RemoteControl {
  3.     private Command[] onCommands;
  4.     private Command[] offCommands;
  5.     private Command undoCommand;
  6.     public RemoteControl() {
  7.         onCommands = new Command[2];
  8.         offCommands = new Command[2];
  9.         Command noCommand = new NoCommand();
  10.         for (int i = 0; i < 2; i++) {
  11.             onCommands[i] = noCommand;
  12.             offCommands[i] = noCommand;
  13.         }
  14.         undoCommand = noCommand;
  15.     }
  16.     public void setCommand(int slot, Command onCommand, Command offCommand) {
  17.         onCommands[slot] = onCommand;
  18.         offCommands[slot] = offCommand;
  19.     }
  20.     public void onButtonWasPushed(int slot) {
  21.         onCommands[slot].execute();
  22.         undoCommand = onCommands[slot];
  23.     }
  24.     public void offButtonWasPushed(int slot) {
  25.         offCommands[slot].execute();
  26.         undoCommand = offCommands[slot];
  27.     }
  28.     public void undoButtonWasPushed() {
  29.         undoCommand.undo();
  30.     }
  31. }
  32. // 空命令类
  33. class NoCommand implements Command {
  34.     @Override
  35.     public void execute() {
  36.         System.out.println("No command assigned");
  37.     }
  38.     @Override
  39.     public void undo() {
  40.         System.out.println("No command assigned");
  41.     }
  42. }
复制代码
5. 客户端代码

  1. public class SmartHomeApp {
  2.     public static void main(String[] args) {
  3.         // 创建设备
  4.         Light livingRoomLight = new Light();
  5.         Fan livingRoomFan = new Fan();
  6.         // 创建命令
  7.         Command lightOn = new LightOnCommand(livingRoomLight);
  8.         Command lightOff = new LightOffCommand(livingRoomLight);
  9.         Command fanOn = new FanOnCommand(livingRoomFan);
  10.         Command fanOff = new FanOffCommand(livingRoomFan);
  11.         // 创建遥控器
  12.         RemoteControl remoteControl = new RemoteControl();
  13.         remoteControl.setCommand(0, lightOn, lightOff);
  14.         remoteControl.setCommand(1, fanOn, fanOff);
  15.         // 操作遥控器
  16.         remoteControl.onButtonWasPushed(0); // 输出: Light is on
  17.         remoteControl.offButtonWasPushed(0); // 输出: Light is off
  18.         remoteControl.undoButtonWasPushed(); // 输出: Light is on
  19.         remoteControl.onButtonWasPushed(1); // 输出: Fan is on
  20.         remoteControl.offButtonWasPushed(1); // 输出: Fan is off
  21.         remoteControl.undoButtonWasPushed(); // 输出: Fan is on
  22.     }
  23. }
复制代码

3. 命令模式的长处


  • 解耦请求的发送者和接收者
    命令模式将请求封装成对象,使得请求的发送者和接收者之间没有直接的依赖关系。
  • 支持取消和重做
    通过实现 undo() 方法,可以轻松实现取消操纵。
  • 支持请求的列队和日志记录
    命令对象可以被存储、传递和记录,从而支持请求的列队和日志记录。
  • 易于扩展
    新增命令时,只需实现新的命令类,无需修改现有代码。

4. 总结

命令模式通过将请求封装成对象,实现了请求的发送者和接收者之间的解耦,从而使得系统更加灵活和可扩展。通过本文的讲授和代码示例,信赖你已经掌握了命令模式的核心头脑和实现方法。在实际开辟中,命令模式非常适实用于实现取消、重做、列队等功能。

互动话题
你在项目中用过命令模式吗?遇到过哪些问题?欢迎在批评区分享你的经验!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表