博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
6 行为型模式之 - 命令模式
阅读量:5164 次
发布时间:2019-06-13

本文共 6252 字,大约阅读时间需要 20 分钟。

命令模式介绍:命令模式相对于其它模式来说并没有那么多的条条框框,不算是一个很“规矩”的模式,不过,就是基于这一点,命令模式相对于其它的设计模式更为灵活,我们接触比较多的命令模式无非就是菜单命令,如在操作系统中,我们点击“关机”命令,系统会执行一系列的操作,如先是暂停处理事件,保存系统的一些配置,然后结束程序进程,最后调用内核命令关闭计算机等,而我闪的命令模式也与之相似。将一系列的方法调用封装,用户只需要调用一个方法执行,那么所有这些被封装的方法就会被挨个执行调用

命令模式定义:将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化,对请求排队或者记录请求日志操作

命令模式使用场景:需要抽象出待执行的动作,然后以参数的形式提供出来 -- 类似于面向过程中的回调,而命令模式正是回调的面向对象的实现。

命令模式主要是命令的请求者与命令的执行者之间的关系,其中命令的里面保存了一个命令执行者的引用 

下面以小时候玩的“俄罗斯方块”游戏为例子,讲解命令模式的用法。

俄罗斯方块游戏中有4个按钮,两个左右的,一个快速落下的,还有一个是变换方块的形状的,一个玩游戏的人就相当于我们的客户端,而游戏上4个按钮就相当于4个请求者或者称为调用者,执行具体按钮命令的逻辑方法可以看作是命令角色。

下面以代码说明。首先是命令的接收者

1 /** 2  * 命令接收者,俄罗斯方块游戏 3  *  4  */ 5 public class TerisMachine { 6  7     //真正处理"向左"操作的逻辑代码 8     public void toLeft(){ 9         System.out.println("向左");10     }11 12     //真正处理"向右"操作的逻辑代码13     public void toRight(){14         System.out.println("向右");15     }16 17     //真正处理"快速向下"操作的逻辑代码18     public void fastToBottom(){19         System.out.println("快速向下");20     }21 22     //真正处理"改变形状"操作的逻辑代码23     public void transform(){24         System.out.println("改变形状");25     }26 }

 TetrisMachine类是整个命令模式中唯一处理具体代码逻辑的地方,其他的类都是直接或者间接地调用到该类的方法,这就是接收者的角色,处理具体的逻辑。

接下来我们定义一个接口命令来作为命令角色的抽象

1 /**2  * 命令角色的抽象3  */4 public interface Command {5     //命令执行的方法6     void execute();7 }

下面分别实现4个命令

1 /** 2  * 向左移动的命令 3  */ 4 public class LeftCommand implements Command{ 5     //持有一个命令执行者的引用 6     TerisMachine terisMachine; 7  8     public void setTerisMachine(TerisMachine terisMachine){ 9         this.terisMachine = terisMachine;10     }11 12     @Override13     public void execute() {14         //调用游戏机里面的方法具体执行15         terisMachine.toLeft();16     }17 }
1 /** 2  * 向右移动的命令 3  */ 4 public class RightCommand implements Command{ 5     //持有一个命令执行者的引用 6     TerisMachine terisMachine; 7  8     public void setTerisMachine(TerisMachine terisMachine){ 9         this.terisMachine = terisMachine;10     }11 12     @Override13     public void execute() {14         //调用游戏机里面的方法具体执行15         terisMachine.toRight();16     }17 }
1 /** 2  * 快速向下的命令 3  */ 4 public class FastToBottomCommand implements Command{ 5     //持有一个命令执行者的引用 6     TerisMachine terisMachine; 7  8     public void setTerisMachine(TerisMachine terisMachine){ 9         this.terisMachine = terisMachine;10     }11 12     @Override13     public void execute() {14         //调用游戏机里面的方法具体执行15         terisMachine.fastToBottom();16     }17 }
1 /** 2  * 改变形状的命令 3  */ 4 public class TransformCommand implements Command{ 5     //持有一个命令执行者的引用 6     TerisMachine terisMachine; 7  8     public void setTerisMachine(TerisMachine terisMachine){ 9         this.terisMachine = terisMachine;10     }11 12     @Override13     public void execute() {14         //调用游戏机里面的方法具体执行15         terisMachine.transform();16     }17 }

 

上面有个相应的4个命令了。下面再实现一个命令的请求者

1 /** 2  * 3  * 命令的请求者 4  */ 5 public class Buttons { 6     //向左移动的命令 7     private LeftCommand leftCommand; 8     //向右移动的命令 9     private RightCommand rightCommand;10     //快速萍的命令11     private FastToBottomCommand fastToBottomCommand;12     //改变形状的命令13     private TransformCommand transformCommand;14 15     //设置向左移动的命令16     public void setLeftCommand(LeftCommand leftCommand) {17         this.leftCommand = leftCommand;18     }19 20     //设置向右移动的命令21     public void setRightCommand(RightCommand rightCommand) {22         this.rightCommand = rightCommand;23     }24 25     //设置快速落下的命令26     public void setFastToBottomCommand(FastToBottomCommand fastToBottomCommand) {27         this.fastToBottomCommand = fastToBottomCommand;28     }29 30     //设置改变形状的命令31     public void setTransformCommand(TransformCommand transformCommand) {32         this.transformCommand = transformCommand;33     }34 35     //按下按钮向左移动36     public void toLeft(){37         leftCommand.execute();38     }39 40     //按下按钮向右移动41     public void toRight(){42         rightCommand.execute();43     }44 45     //按下按钮快速落下46     public void fall(){47         fastToBottomCommand.execute();48     }49 50     //按下按钮改变形状51     public void transform(){52         transformCommand.execute();53     }54 55 }

 

最后由客户端来决定如何使用

客户端类:

1 /** 2  * 玩家,也是客户端 3  */ 4 public class Player { 5     public static void main(String[] args){ 6         test1(); 7     } 8  9     //测试命令模式10     private static void test1() {11         //俄罗斯方块游戏12         TerisMachine terisMachine = new TerisMachine();13 14         //根据游戏我们造4种命令15         LeftCommand leftCommand = new LeftCommand();16         RightCommand rightCommand = new RightCommand();17         FastToBottomCommand fastToBottomCommand = new FastToBottomCommand();18         TransformCommand transformCommand = new TransformCommand();19 20         //引用一个命令的具体执行者21         leftCommand.setTerisMachine(terisMachine);22         rightCommand.setTerisMachine(terisMachine);23         fastToBottomCommand.setTerisMachine(terisMachine);24         transformCommand.setTerisMachine(terisMachine);25 26         //按钮可以执行不同的命令27         Buttons buttons = new Buttons();28         buttons.setLeftCommand(leftCommand);29         buttons.setRightCommand(rightCommand);30         buttons.setFastToBottomCommand(fastToBottomCommand);31         buttons.setTransformCommand(transformCommand);32 33         //具体按下哪个键玩家说了算34         buttons.toLeft();35         buttons.toRight();36         buttons.fall();37         buttons.transform();38     }39 40     //对于大部分开发者来说很容易接受下面的代码41     private static void test2(){42         //俄罗斯方块游戏43         TerisMachine machine = new TerisMachine();44 45         //要实现怎样的控制,直接调用相应的函数就行46         machine.toLeft();47         machine.toRight();48         machine.fastToBottom();49         machine.transform();50     }51 52 53 }

或者大家在看了这一长篇代码后心存疑惑,明明就是一个很简单的问题,为什么要做的如此复杂呢?对于大部分的开发者来说更愿意接受上面的 test2()中的代码,也就是:

    //对于大部分开发者来说很容易接受下面的代码41     private static void test2(){42         //俄罗斯方块游戏43         TerisMachine machine = new TerisMachine();44 45         //要实现怎样的控制,直接调用相应的函数就行46         machine.toLeft();47         machine.toRight();48         machine.fastToBottom();49  machine.transform(); 50  }

 

调用逻辑做得如此复杂,这是因为开发起来方便,每次我们增加或者修改游戏功能只需要修改 TetrisMachine类就行了,然后对应的改一改Player类,一切都很方便。但是,对开发者自己来说是方便了,那么,如果有一天开发者不再负责这个项目了呢?这样的逻辑留给后来者,没有人会觉得方便。设计模式有一条很重要的原则:对修改关闭,对扩展开放。大家可以细细体会。

 

 

 

posted on
2017-04-18 21:12  阅读(
...) 评论(
...) 收藏

转载于:https://www.cnblogs.com/start1225/p/6729708.html

你可能感兴趣的文章
10种ADC软件滤波方法及程序
查看>>
[Debug]GDB学习笔记(一)
查看>>
SpringBoot 配置阿里巴巴Druid连接池
查看>>
java学习日记-------------------------------------贪吃蛇
查看>>
Android 核心组件 Activity 之下
查看>>
java 网络编程(二)----UDP基础级的示例
查看>>
买书折扣问题
查看>>
MVC 数据验证
查看>>
详细解析ASP.NET中Request接收参数乱码原理
查看>>
REST风格的原则
查看>>
jquery数组(排序)
查看>>
CSS基本相关内容--中秋特别奉献
查看>>
GitHub 优秀的 Android 开源项目
查看>>
让窗体自适应屏幕
查看>>
vim插件之marks
查看>>
常用 SQL 命令和ASP 编程
查看>>
根据天气api获取城市天气
查看>>
Codeforces Round #563 (Div. 2)
查看>>
cocos2d动画加载
查看>>
C语言数组篇(五)多级指针和二维数组指针的区别
查看>>