=========================
命令模式:
=========================
废话不说了,先看例子:
模拟对电视机的操作有开机、关机、换台命令。代码如下
Command角色--定义命令的接口,声明执行的方法。
1 //执行命令的接口 2 public interface Command { 3 void execute(); 4 }
Receive角色--命令接收者,真正执行命令的对象。实现命令要求实现的相应功能。
1 //命令接收者Receiver 2 public class Tv { 3 public int currentChannel = 0; 4 5 public void turnOn() { 6 System.out.println("The televisino is on."); 7 } 8 9 public void turnOff() { 10 System.out.println("The television is off."); 11 } 12 13 public void changeChannel(int channel) { 14 this.currentChannel = channel; 15 System.out.println("Now TV channel is " + channel); 16 } 17 }
ConcreteCommand角色--通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。一般一个命令对应一个对象,分别是CommandOn,CommandOff,CommandChange
commandon对象:
1 //开机命令ConcreteCommand 2 public class CommandOn implements Command { 3 private Tv myTv; 4 5 public CommandOn(Tv tv) { 6 myTv = tv; 7 } 8 9 public void execute() { 10 myTv.turnOn(); 11 } 12 }
commandoff对象:
1 //关机命令ConcreteCommand 2 public class CommandOff implements Command { 3 private Tv myTv; 4 5 public CommandOff(Tv tv) { 6 myTv = tv; 7 } 8 9 public void execute() { 10 myTv.turnOff(); 11 } 12 }
commandchange对象:
1 //频道切换命令ConcreteCommand 2 public class CommandChange implements Command { 3 private Tv myTv; 4 5 private int channel; 6 7 public CommandChange(Tv tv, int channel) { 8 myTv = tv; 9 this.channel = channel; 10 } 11 12 public void execute() { 13 myTv.changeChannel(channel); 14 } 15 }
Invoker角色--持有很多的命令对象,这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
1 //可以看作是遥控器Invoker 2 public class Control { 3 private Command onCommand, offCommand, changeChannel; 4 5 public Control(Command on, Command off, Command channel) { 6 onCommand = on; 7 offCommand = off; 8 changeChannel = channel; 9 } 10 11 public void turnOn() { 12 onCommand.execute(); 13 } 14 15 public void turnOff() { 16 offCommand.execute(); 17 } 18 19 public void changeChannel() { 20 changeChannel.execute(); 21 } 22 }
Client角色--组装命令对象和接收者创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者
1 //测试类Client 2 public class Client { 3 public static void main(String[] args) { 4 // 命令接收者Receiver 5 Tv myTv = new Tv(); 6 // 开机命令ConcreteCommond 7 CommandOn on = new CommandOn(myTv); 8 // 关机命令ConcreteCommond 9 CommandOff off = new CommandOff(myTv); 10 // 频道切换命令ConcreteCommond 11 CommandChange channel = new CommandChange(myTv, 2); 12 // 命令控制对象Invoker 13 Control control = new Control(on, off, channel); 14 15 // 开机 16 control.turnOn(); 17 // 切换频道 18 control.changeChannel(); 19 // 关机 20 control.turnOff(); 21 } 22 }
执行结果
1 The televisino is on. 2 Now TV channel is 2 3 The television is off.
看完代码,是不是对命令模式有个大概的了解了。
1.命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
2.每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
3.命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
4.命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
5.命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
下面看下类图:
角色分析:
Command: 抽象命令类。用来声明执行操作的接口。
ConcreteCommand: 具体命令类。将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Excute。
Invoker: 调用者。要求该命令执行这个请求。
Receiver: 接收者。知道如何实施与执行一个请求相关的操作,任何类都有可能成为一个接收者。
Client:客户类。
优点
1.降低对象之间的耦合度。
2.新的命令可以很容易地加入到系统中。
3.可以比较容易地设计一个组合命令。
4.调用同一方法实现不同的功能
缺点
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。
适用情况
1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
2.系统需要在不同的时间指定请求、将请求排队和执行请求。
3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
4.系统需要将一组操作组合在一起,即支持宏命令。
文章来源:
http://blog.csdn.net/jason0539/article/details/45110355
http://www.cnblogs.com/chenssy/p/3357683.html