继续设计模式哈,今天带来命令模式,二话不说,先看定义:

定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

这尼玛定义,看得人蛋疼,看不明白要淡定,我稍微简化一下:将请求封装成对象,将动作请求者和动作执行者解耦。好了,直接用例子来说明。

需求:最近智能家电很火热啊,未来尼玛估计冰箱都会用支付宝自动买东西了,,,,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。

这个需求一看,尼玛要是没有什么个性化、扩展性还好说啊,直接针对每个遥控器的按钮onClick,然后在里面把代码写死就搞定了,但是个性化怎么整,还要有扩展性。。。

好了,下面命令模式出场,命令模式的核心就是把命令封装成类,对于命令执行者不需要知道现在执行的具体是什么命令。

1、首先看下我们拥有的家电的API:

[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 门
  4. * @author zhy
  5. *
  6. */
  7. public class Door
  8. {
  9. public void open()
  10. {
  11. System.out.println("打开门");
  12. }
  13. public void close()
  14. {
  15. System.out.println("关闭门");
  16. }
  17. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 电灯
  4. * @author zhy
  5. *
  6. */
  7. public class Light
  8. {
  9. public void on()
  10. {
  11. System.out.println("打开电灯");
  12. }
  13. public void off()
  14. {
  15. System.out.println("关闭电灯");
  16. }
  17. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 电脑
  4. * @author zhy
  5. *
  6. */
  7. public class Computer
  8. {
  9. public void on()
  10. {
  11. System.out.println("打开电脑");
  12. }
  13. public void off()
  14. {
  15. System.out.println("关闭电脑");
  16. }
  17. }

看来我们有电灯、电脑、和门,并且开关的接口的设计好了。接下来看如何把命令封装成类:

[java] view plain copy
  1. package com.zhy.pattern.command;
  2. public interface Command
  3. {
  4. public void execute();
  5. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 关闭电灯的命令
  4. * @author zhy
  5. *
  6. */
  7. public class LightOffCommond implements Command
  8. {
  9. private Light light ;
  10. public LightOffCommond(Light light)
  11. {
  12. this.light = light;
  13. }
  14. @Override
  15. public void execute()
  16. {
  17. light.off();
  18. }
  19. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 打开电灯的命令
  4. * @author zhy
  5. *
  6. */
  7. public class LightOnCommond implements Command
  8. {
  9. private Light light ;
  10. public LightOnCommond(Light light)
  11. {
  12. this.light = light;
  13. }
  14. @Override
  15. public void execute()
  16. {
  17. light.on();
  18. }
  19. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 开电脑的命令
  4. * @author zhy
  5. *
  6. */
  7. public class ComputerOnCommond implements Command
  8. {
  9. private Computer computer ;
  10. public ComputerOnCommond( Computer computer)
  11. {
  12. this.computer = computer;
  13. }
  14. @Override
  15. public void execute()
  16. {
  17. computer.on();
  18. }
  19. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 关电脑的命令
  4. * @author zhy
  5. *
  6. */
  7. public class ComputerOffCommond implements Command
  8. {
  9. private Computer computer ;
  10. public ComputerOffCommond( Computer computer)
  11. {
  12. this.computer = computer;
  13. }
  14. @Override
  15. public void execute()
  16. {
  17. computer.off();
  18. }
  19. }

好了,不贴那么多了,既然有很多命令,按照设计原则,我们肯定有个超类型的Command,然后各个子类,看我们把每个命令(请求)都封装成类了。接下来看我们的遥控器。

[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 控制器面板,一共有9个按钮
  4. *
  5. * @author zhy
  6. *
  7. */
  8. public class ControlPanel
  9. {
  10. private static final int CONTROL_SIZE = 9;
  11. private Command[] commands;
  12. public ControlPanel()
  13. {
  14. commands = new Command[CONTROL_SIZE];
  15. /**
  16. * 初始化所有按钮指向空对象
  17. */
  18. for (int i = 0; i < CONTROL_SIZE; i++)
  19. {
  20. commands[i] = new NoCommand();
  21. }
  22. }
  23. /**
  24. * 设置每个按钮对应的命令
  25. * @param index
  26. * @param command
  27. */
  28. public void setCommand(int index, Command command)
  29. {
  30. commands[index] = command;
  31. }
  32. /**
  33. * 模拟点击按钮
  34. * @param index
  35. */
  36. public void keyPressed(int index)
  37. {
  38. commands[index].execute();
  39. }
  40. }
[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * @author zhy
  4. *
  5. */
  6. public class NoCommand implements Command
  7. {
  8. @Override
  9. public void execute()
  10. {
  11. }
  12. }

注意看到我们的遥控器有9个按钮,提供了设置每个按钮的功能和点击的方法,还有注意到我们使用了一个NoCommand对象,叫做空对象,这个对象的好处就是,我们不用执行前都判断个if(!=null),并且提供了一致的操作。

最后测试一下代码:

[java] view plain copy
  1. package com.zhy.pattern.command;
  2. public class Test
  3. {
  4. public static void main(String[] args)
  5. {
  6. /**
  7. * 三个家电
  8. */
  9. Light light = new Light();
  10. Door door = new Door();
  11. Computer computer = new Computer();
  12. /**
  13. * 一个控制器,假设是我们的app主界面
  14. */
  15. ControlPanel controlPanel = new ControlPanel();
  16. // 为每个按钮设置功能
  17. controlPanel.setCommand(0, new LightOnCommond(light));
  18. controlPanel.setCommand(1, new LightOffCommond(light));
  19. controlPanel.setCommand(2, new ComputerOnCommond(computer));
  20. controlPanel.setCommand(3, new ComputerOffCommond(computer));
  21. controlPanel.setCommand(4, new DoorOnCommond(door));
  22. controlPanel.setCommand(5, new DoorOffCommond(door));
  23. // 模拟点击
  24. controlPanel.keyPressed(0);
  25. controlPanel.keyPressed(2);
  26. controlPanel.keyPressed(3);
  27. controlPanel.keyPressed(4);
  28. controlPanel.keyPressed(5);
  29. controlPanel.keyPressed(8);// 这个没有指定,但是不会出任何问题,我们的NoCommand的功劳
  30. }
  31. }

输出结果:

可以看到任意按钮可以随意配置任何命令,再也不需要尼玛的变一下需求改代码了,随便用户怎么个性化了。其实想白了,这里的设置我们还可以配置到一个配置文件中,完全的解耦有木有。

好了,用户对于这个按钮可能还不是太满意,用户希望夜深人静的时候,能够提供个按钮直接关门、关灯、开电脑,,,,大家懂的,,,我们稍微修改下代码,满足他

定义一个命令,用户干一些列的事,可配置,且与原来的命令保持接口一致:

[java] view plain copy
  1. package com.zhy.pattern.command;
  2. /**
  3. * 定义一个命令,可以干一系列的事情
  4. *
  5. * @author zhy
  6. *
  7. */
  8. public class QuickCommand implements Command
  9. {
  10. private Command[] commands;
  11. public QuickCommand(Command[] commands)
  12. {
  13. this.commands = commands;
  14. }
  15. @Override
  16. public void execute()
  17. {
  18. for (int i = 0; i < commands.length; i++)
  19. {
  20. commands[i].execute();
  21. }
  22. }
  23. }

好了,已经满足屌丝的需求了。我们测试看看。

[java] view plain copy
  1. // 定义一键搞定模式
  2. QuickCommand quickCommand = new QuickCommand(new Command[] { new DoorOffCommond(door),
  3. new LightOffCommond(light), new ComputerOnCommond(computer) });
  4. System.out.println("****点击一键搞定按钮****");
  5. controlPanel.setCommand(8, quickCommand);
  6. controlPanel.keyPressed(8);

是不是很完美。

最后,继续来谈谈命令模式,命令模式就是把命令封装成对象,然后将动作请求者与动作执行者完全解耦,上例中遥控器的按钮和电器一毛钱关系都没吧。

还记得定义中提到了队列,命令模式如何用于队列呢,比如饭店有很多个点菜的地方,有一个做菜的地方,把点菜看作命令,做菜看作命令执行者,不断有人点菜就相当于把菜加入队列,对于做菜的只管从队列里面取,取一个做一个。

定义中还提到了日志,日志一般用于记录用户行为,或者在异常时恢复时用的,比如每个命令现在包含两个方法,一个执行execute,一个undo(上例中为了方便大家理解,没有写undo),我们可以把用户所有命令调用保存到日志中,比如用户操作不当了,电器异常了,只需要把日志中所有的命令拿出来执行一遍undo就完全恢复了,是吧,就是这么个意思。

好了,各位留个言、点个赞算是对我的支持,多谢大家~

设计模式 命令模式 之 管理智能家电相关推荐

  1. 设计模式 命令模式 之 管理智能家电

    继续设计模式哈,今天带来命令模式,二话不说,先看定义: 定义:将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 这尼玛定义,看得 ...

  2. Python设计模式-命令模式

    Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...

  3. 设计模式 命令模式 实例_根据您的命令-命令设计模式

    设计模式 命令模式 实例 命令设计模式是一种广为人知的设计模式,属于行为设计模式("四人帮"的一部分). 顾名思义,它与应用程序中的动作和事件有关. 问题陈述: 假设有一个网页将在 ...

  4. C语言设计模式——命令模式

    C语言设计模式--命令模式 好处:让代码清晰明了,容易添加和删除,易维护. 哪些地方会用到命令模式?(列出几个常见的例子) 1.按键处理,每个按键按下得到一个索引(指的就是命令),一个按键对应一个处理 ...

  5. C语言实现设计模式—命令模式

    文章目录 C语言设计模式--命令模式 传统的实现方式如下:(伪代码) 命令模式优化 UML 用例说明 实现流程 command.h command.c main 总结 C语言设计模式--命令模式 好处 ...

  6. 游戏设计模式 - 命令模式在Unity中的应用(C#)

    游戏设计模式 - 命令模式在Unity中的应用(C#) 实测:这是一篇简单易懂的文章-> https://zhuanlan.zhihu.com/p/46937284

  7. C++设计模式——命令模式(command pattern)

    一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...

  8. 小菜学设计模式——命令模式

    2019独角兽企业重金招聘Python工程师标准>>> 背景 外面小摊与店面的比较,你就会发现,店面似乎更加容易管理,为什么呢?因为在客户与老板自己新增了很多员工,这些员工各司其职, ...

  9. 游戏设计模式---命令模式

    命令模式 游戏设计模式Design Patterns Revisited 命令模式是我最喜欢的模式之一. 大多数我写的游戏或者别的什么之类的大型程序,都会在某处用到它. 当在正确的地方使用时,它可以将 ...

最新文章

  1. html text alt,HTML alt text for image maps
  2. python面试题之“该死的for循环系列”(二)
  3. 尝试cython和openmp
  4. MySQL innodb_page_size
  5. 一道面试题:遇到大规模Oracle坏块该怎么处理?
  6. 2018-2019-1 20165202 20165210 20165214 实验二 固件程序设计
  7. matlab写实对角矩阵,Matlab对角矩阵
  8. 仿新浪微博布局学习——妙用TabHost
  9. 从冬奥会看中国科技:全民感谢的高速摄像机,有何玄机?
  10. winform TreeView节点中的CheckBox 禁用
  11. 使用Proxmox 和 Deskpool 搭建桌面云系统
  12. 计算机信息管理发展的重要性,从历史情况看,计算机信息管理的发展过程是( )...
  13. 京东书籍信息及评论内容爬取
  14. 电子合同的一个“安全漏洞”
  15. 「表白神器」Python超火隐藏表白图 你能看出来吗?「附源码」
  16. filebeat7.7.0相关详细配置预览- processors - add_host_metadata
  17. SaaS从业者必读:一文读懂如何衡量与优化SaaS公司的关键指标
  18. python如何调用pyc
  19. 变电站综合自动化系统如何提高综合性自动化功能?
  20. 根据列名提取指定列 shell awk

热门文章

  1. spark ml 聚类源码笔记二
  2. Matplotlib多子图显示2——网格划分
  3. 无线网络的加密方式:WEP、WPA和WPA2(转)
  4. Netty线程模型 Reactor模型
  5. Cocos2d坐标系详解
  6. Unity3D 编译发布(Publishing Builds)
  7. AI 世界里,挖掘机「生产」哪家强?
  8. c# 使用多个TASK事务,等待返回值
  9. JAVA学生信息管理系统(数据库实现)
  10. 【瑕疵检测】瓶盖瑕疵检测【含Matlab源码 730期】