命令模式(Command Pattern),是行为型模式之一。在日常生活和开发过程中,这是一个非常常见的设计模式,比如我们电脑关机这个操作,我们只需要点击关机键便可以实现关机,内部是通过什么进行关机的,我们不需要去知道,计算机会帮我们实现这个功能。
优点:
(1)比较容易地实现一个命令队列。
(2)比较容易将队列记入日志。
(3)请求者和实现者通过接口进一步解耦。
(4)可以容易地实现对请求的撤销和恢复。
(5)加入新的命令不影响其它类的操作。
引用上述关机的例子,对名词进行一些解释:
·Client(客户端):此处为我们自己,创建一个具体命令(ConcreteCommand)对象并确定其接收者。
·Invoker(请求者):关机键,负责调用命令对象执行请求,相关的方法叫做行动方法。
·Command(命令):声明了一个给所有具体命令类的抽象接口。
·ConcreteCommand(具体命令):调用关机的操作。
·Receicer(接收者):实现关机的操作。
接收者角色类
1 public class Receiver
2 {
3 /**
4 * 真正执行命令相应的操作
5 */
6 public void action(){
7 System.out.println("执行操作");
8 }
9 }
抽象命令角色类
1 public interface Command
2 {
3 void execute();
4 }
具体命令角色类
1 public class ConcreteCommand implements Command
2 {
3 private Receiver receiver;
4
5 public ConcreteCommand(Receiver receiver)
6 {
7 this.receiver = receiver;
8 }
9
10 public void execute() {
11 // 调用并执行命令
12 receiver.action();
13 }
14 }
请求者角色类
1 public class Invoker
2 {
3 private Command command;
4
5 public Invoker(Command command)
6 {
7 this.command = command;
8 }
9
10 /**
11 * 行动方法,和Receive中的action()方法名称相同,却没有半毛钱关系
12 */
13 public void action(){
14
15 command.execute();
16 }
17 }
客户端
1 public class Client
2 {
3
4 /**
5 * created by zm on 16-05-22
6 */
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 //创建接收者
10 Receiver receiver = new Receiver();
11 //创建命令对象,设定它的接收者
12 Command command = new ConcreteCommand(receiver);
13 //创建请求者,把命令对象设置进去
14 Invoker invoker = new Invoker(command);
15 //执行方法
16 invoker.action();
17 }
18 }
现在我们在具体点讲一个事例,此处是开发过程中遇到的一个例子,在过去的开发中,曾经有一个界面,上面有着多处第三方登录,比如QQ登录,新浪微博登录,微信登录…
接收者角色类
1 public class Receiver
2 {
3 public void tencentLogin(){
4 System.out.println("QQ登录");
5 }
6
7 public void weChatLogin(){
8 System.out.println("weChat登录");
9 }
10
11 public void sinaLogin(){
12 System.out.println("sina登录");
13 }
14 }
抽象命令角色类
1 public interface Command
2 {
3 void execute();
4 }
具体命令角色类
1 public class SinaCommand implements Command
2 {
3 private Receiver receiver;
4
5 public SinaCommand(Receiver receiver)
6 {
7 this.receiver = receiver;
8 }
9
10 public void execute() {
11 receiver.sinaLogin();
12 }
13 }
1 public class TencentCommand implements Command
2 {
3 private Receiver receiver;
4
5 public TencentCommand(Receiver receiver)
6 {
7 this.receiver = receiver;
8 }
9
10 public void execute() {
11 receiver.tencentLogin();
12 }
13 }
1 public class WeChatCommand implements Command
2 {
3 private Receiver receiver;
4
5 public WeChatCommand(Receiver receiver)
6 {
7 this.receiver = receiver;
8 }
9
10 public void execute() {
11 receiver.weChatLogin();
12 }
13 }
请求者角色类
1 public class Invoker
2 {
3 //开发过程中没有此属性,此处作为示例,用来便利和撤销操作
4 private static List<Command> list = new ArrayList<Command>();
5
6 public Invoker(Command command)
7 {
8 list.add(command);
9 }
10
11 public void action(Command command){
12 command.execute();
13 }
14
15 public void removeAction(Command command){
16 if(list.contains(command)){
17 System.out.println(command.getClass().getName()+"被移除");
18 list.remove(command);
19 }
20 }
21
22 public void allAction(){
23 if(list.size()>0){
24 for (Command mCommand : list)
25 {
26 mCommand.execute();
27 }
28 }
29 }
30 }
客户端角色类
1 public class Client
2 {
3
4 /**
5 * created by zm on 16-05-22
6 */
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 //创建接收者
10 Receiver receiver = new Receiver();
11 //创建命令对象,设定它的接收者
12 Command tencentCommand = new TencentCommand(receiver);
13 Command weChatCommand = new WeChatCommand(receiver);
14 Command sinaCommand = new SinaCommand(receiver);
15 //创建请求者,把命令对象设置进去
16 Invoker invoker = new Invoker(tencentCommand);
17 invoker = new Invoker(weChatCommand);
18 invoker = new Invoker(sinaCommand);
19 //执行方法
20 invoker.allAction();
21 System.out.println(".................");
22 invoker.removeAction(tencentCommand);
23 System.out.println(".................");
24 invoker.allAction();
25 }
26 }
执行后的结果如下:
QQ登录
weChat登录
sina登录
……………..
com.zm.zero.TencentCommand被移除
……………..
weChat登录
sina登录
总结:敏捷开发告诉我们,不要为了添加基于猜测的、实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
参考文献:《Java与模式》、《大话设计模式》《head first 设计模式》