java之命令模式
Posted 朱洪昌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java之命令模式相关的知识,希望对你有一定的参考价值。
实际生活中常有的例子,比如银行吧,在早些年,到银行办理业务,一堆人围着大堂经理问,什么业务该去什么地方办理,哎。。。。,一个问题一天要跟上百号人都解释一遍,你好,这个业务呢,你可以去XX柜台咨询一下,那这个业务呢,你可以去XY柜台咨询,有时候,可能出现错误,返回来回问好几遍,好烦哦。。。。,经理是何等的无奈,但为了客户至上的原则,总是微笑,在微笑。何时是解脱之日啊。哈哈,随着科技的发展,经理们终于从这苦难的日子里解脱了,那就是业务办理区取号机,现在简单的操作就可以耐心等候办理,既方便客户,也解脱了经理,真是造福大众的一件好事。根据办理业务的不同,系统自动分发给各自擅长的业务员哪里,按着号码一次处理。言归正传,上面的例子就命令模式的真实写照,业务办理取号机,将客户的对于业务的请求,统一的接纳,进行分类处理,对于不同的业务,安排到不同的业务员手中处理,避免之前繁琐的过程。
命令模式的定义:Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,请求排队或者记录请求日志,可以提供命令的撤销和恢复功能),说白了,就是把请求封装成对象,以统一应对不同的请求,做出响应。
命令模式的通用图解:
解释上述图解的关键词:
Client:创建一个具体的命令对象(ConcreteCommand1 or ConcreteCommand2 ...)并设定它的接收者(ConcreteReceiver1 or ConcreteReceiver2....), 说白了,就是写个测试类,创建命令对象和接收者对象初始化一个Invoker,测试命令模式。在实际生活中,对于一个系统,有各种不同的请求,系统无法知道,发送来的请求要什么Command处理和这个Command的最终处理者,就需要有一个总代理就像我们项目的接口人(Invoker)一样,某个涉及到项目的问题先问接口人,然后接口人在安排,哪一个功能小组(具体的Command),小组再安排具体谁来处理(具体的Receiver),而一般发问题的一方,都知道是哪个更能模块出了问题,该找谁解决,但我们都有自己的事,如果这来问一下,那来问一下,那还怎么工作。接口人就可以让工作有秩序的进行。这样下来,接收者也就是想我们一样,屌丝码农,不用跟其他项目的人直接打交道,也避免了,很多麻烦,同样也使得我们的工作,更专注,更高效,不是???
Invoker:要求该命令执行这个请求,安排人,解决问题,包括Command的属性参数,Command的set方法,和引用Command的execute()方法实现的Action()方法
Command : 声明执行操作的接口,抽象类,ConcreteCommand 继承该 Command,具体该是用什么操作处理这事?哪个功能小组能处理这事?至少包括一个execute()方法,或者可以加一个Receiver,更抽象一层,那么ConcreteCommand,就好不用包括Receiver,只要初始化就好
ConcreteCommand:将一个接收者对象绑定在某一个动作上,调用接收者的相应操作,以实现Execute的方法,继承自Command,实现execute方法,包括Receiver,用Receiver来实现execute方法
Receiver:知道如何实施和执行一个请求的相关操作,任何类都可可以作为一个接收者,可以是类或者抽象类,抽象类有对应ConcreteReceiver实现
同时注意根据定义,对于Command中应该包括,命令撤销执行和恢复的状态的功能,具体的在Command添加相关方法,在具体实现类中实现即可
代码实现例子:
1 public class Invoker 2 { 3 private Command command; 4 5 /** 6 * 设置 command 7 * 8 * @param command 对 command 进行赋值 9 */ 10 public void setCommand(Command command) 11 { 12 this.command = command; 13 } 14 15 public void action() 16 { 17 command.execute(); 18 } 19 } 20 21 public abstract class Command 22 { 23 public abstract void execute(); 24 } 25 26 public class ConcreteCommand1 extends Command 27 { 28 private Receiver receiver; 29 /** 30 * @param receiver 31 */ 32 public ConcreteCommand1(Receiver receiver) 33 { 34 this.receiver = receiver; 35 } 36 37 /** { @inheritDoc } */ 38 public void execute() 39 { 40 receiver.doSomething(); 41 } 42 43 } 44 45 public class ConcreteCommand2 extends Command 46 { 47 private Receiver receiver; 48 /** 49 * @param receiver 50 */ 51 public ConcreteCommand2(Receiver receiver) 52 { 53 this.receiver = receiver; 54 } 55 56 /** { @inheritDoc } */ 57 @Override 58 public void execute() 59 { 60 receiver.doSomething(); 61 } 62 63 } 64 65 public abstract class Receiver 66 { 67 public abstract void doSomething(); 68 } 69 70 public class ConcreteReceiver1 extends Receiver 71 { 72 73 /** { @inheritDoc } */ 74 @Override 75 public void doSomething() 76 { 77 // TODO Auto-generated method stub 78 } 79 80 } 81 82 public class ConcreteReceiver2 extends Receiver 83 { 84 85 /** { @inheritDoc } */ 86 @Override 87 public void doSomething() 88 { 89 // TODO Auto-generated method stub 90 } 91 92 } 93 94 public class Client 95 { 96 public static void main(String[] args) 97 { 98 // 首先声明调用者Invoker 99 Invoker invoker = new Invoker(); 100 // 定义接收者 101 Receiver receiver = new ConcreteReceiver1(); 102 // 定义一个发送给接收者的命令 103 Command command = new ConcreteCommand1(receiver); 104 // 把命令交给调用者去执行 105 invoker.setCommand(command); 106 invoker.action(); 107 } 108 }
命令模式的优缺点
优点:1.将调用操作的对象与知道如何实现该操作的对象解耦,请求与具体实现相解耦
2.Command是头等的对象,他可以像其他对象一样被操作和扩展,易扩展,你可以很容易的添加Command而不需要改变现有的类,也可以很轻松的将多个Command装配成一个复合的命令
缺点:几乎都要针对不同的命令,新增不同的类,增加系统复杂度
以上是关于java之命令模式的主要内容,如果未能解决你的问题,请参考以下文章
JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段