设计模式(七)学习----命令模式
命令模式的定义:
模式的组成:
* 抽象命令类(Command):声明执行操作的接口。调用接收者TVReceiver响应的操作,以实现执行的方法execute。
* 具体命令类(TvChangeCommand,TvCloseCommand,TvOpenCommand):创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
* 调用者(RemoteControllerInvoke 遥控器调用类,请求的发送者):要求该命令执行这个请求,通常会持有命令对象,可以持有很多的命令对象。
* 接收者(TVReceiver 电视机,请求的接收者): 知道如何实施和执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的功能。
* 客户端(ConmandClient):创建具体的命令对象,并且创建设置命令的接收者。真正的使用命令客户端是从RemoteControllerInvoke来触发执行的。
形象的类比:
电视机遥控器 :
电视机是请求的接收者,
遥控器是请求的发送者,
遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,
有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。
显然,电视机遥控器就是一个典型的命令模式应用实例。
1.声明执行操作的接口,抽象命令类:
public interface Command { /** * 执行命令的方法 */ void execute(); }
2.具体命令类:
package desigh.commands.commands; /** * 具体电视关闭的命令 * * @author lipeng24@meituan.com * @create 2017-10-18 下午2:39 **/ public class TvChangeCommand implements Command { private TVReceiver tvReceiver; /** * 构造方法,传入响应的接收对象 * * @param receiver */ public TvChangeCommand(TVReceiver receiver) { this.tvReceiver = receiver; } /** * 具体的执行的方法 */ @Override public void execute() { tvReceiver.changeTV(); } }
package desigh.commands.commands; /** * 具体电视关闭的命令 * * @author lipeng24@meituan.com * @create 2017-10-18 下午2:39 **/ public class TvCloseCommand implements Command { private TVReceiver tvReceiver; /** * 构造方法,传入响应的接收对象 * * @param receiver */ public TvCloseCommand(TVReceiver receiver) { this.tvReceiver = receiver; } /** * 具体的执行的方法 */ @Override public void execute() { tvReceiver.closeTV(); } }
package desigh.commands.commands; /** * 具体电视打开的命令 * * @author lipeng24@meituan.com * @create 2017-10-18 下午2:39 **/ public class TvOpenCommand implements Command { private TVReceiver tvReceiver; /** * 构造方法,传入响应的接收对象 * * @param receiver */ public TvOpenCommand(TVReceiver receiver) { this.tvReceiver = receiver; } /** * 具体的执行的方法 */ @Override public void execute() { tvReceiver.openTV(); } }
3.具体命令类接收者类:
package desigh.commands.commands; /** * 电视机接收命令 receiver * * @author lipeng24@meituan.com * @create 2017-10-18 下午12:37 **/ public class TVReceiver { /** * 真正执行命令 */ public void openTV() { System.out.println("open TV "); } /** * 关闭电视 */ public void closeTV() { System.out.println("close TV "); } /** * 电视换台 */ public void changeTV() { System.out.println("change TV menu"); } }
4.遥控器调用者类
package desigh.commands.commands; import java.util.ArrayList; import java.util.List; /** * 遥控器调用类 * * * * @author lipeng24@meituan.com * @create 2017-10-18 下午2:49 **/ public class RemoteControllerInvoke { private List<Command> commands = new ArrayList<>(); /** * * @param cmd */ public void operateTvCommand(Command cmd) { this.commands.add(cmd); System.out.println(commands); cmd.execute(); } }
5 客户端
package desigh.commands.commands; /** * 入口client * * @author lipeng24@meituan.com * @create 2017-10-18 下午2:56 **/ public class ConmandClient { /** * 输出结果: * open TV * change TV menu * close TV * * @param args */ public static void main(String[] args) { // 这里还可以抽象一层,不同的电器除了电视机还有空调,灯等电器 TVReceiver receiver = new TVReceiver(); Command openCommand = new TvOpenCommand(receiver); Command closeCommand = new TvCloseCommand(receiver); Command changeCommand = new TvChangeCommand(receiver); RemoteControllerInvoke remoteControllerInvoke = new RemoteControllerInvoke(); //remoteControllerInvoke 遥控器遥控遥控器上面的命令,电视机接收3个命令之后执行方法 remoteControllerInvoke.operateTvCommand(openCommand); remoteControllerInvoke.operateTvCommand(changeCommand); remoteControllerInvoke.operateTvCommand(closeCommand); } }
命令模式的优点:
* 1.降低系统的耦合度:将调用操作的对象与知道如何实现该操作的对象解耦
* 2.组合命令:可以将多个命令分配成一个组合命令,可以比较容易的设计一个命令队列和宏命令。
* 3.符合开闭原则:增加新的具体的Command很容易,无需改变现有的类
* 4.可以方便的实现对请求或者说命令的Undo撤销和Redo恢复
缺点:导致某些系统有过多的具体命令类。
总结与分析:
1 命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
2 每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作
3 命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
4 命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
5 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
参考:
http://blog.csdn.net/hguisu/article/details/7549895
https://foolchild.cn/2016/07/26/command
https://en.wikipedia.org/wiki/Command_patter
执行框架:LogicUnitExecutor(invoker),LogicUnitQueueGroup(command)
Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.
面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!