什么是命令模式?
从生活中这个很好理解,遥控器电视机就是一个典型的命令模式.
命令模式的概念:“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)----当你彻底了解析命令模式后,在回过头来理解这句话.
为什么要用命令模式?
理解为什么要用命令模式,是学习命令模式的关键.
深入理解命令模式:
1.命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
2.每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
3.命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
4.命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。--因为这个特点就可以实现概念中提到的“记录、撤销/重做、事务”等处理,
5.命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
上面这5点对命令模式进行了更深一步的解析.对理解和设计命令模式都非常有帮助.
/** * 设计一灯类,作为行为的实现者. */ public class Light { //灯的位置 String loc=""; public Light(String loc){ this.loc=loc; } public void On(){ System.out.println(loc+" On"); } public void Off(){ System.out.println(loc+" Off"); } }
/** * 命令的抽象接口 * 深入理解命令模式中的第5点 */ public interface Command { public void execute(); public void undo(); }
每一个命令都对应一个类
/** * 开灯的命令 * 深入理解命令模式中的第4点 */ public class LightOffCommand implements Command{ private Light light; public LightOffCommand(Light light){ this.light=light; } @Override public void execute() { // TODO Auto-generated method stub light.Off(); } @Override public void undo() { // TODO Auto-generated method stub } }
/** * 行为请求者 的接口,就是遥控器接口 */ public interface Control { public void onButton(int slot); public void offButton(int slot); }
/** * 行为请求者的实现,控制器的实现 * 这个也是关健 */ public class MedoControl implements Control { private Command[] onCommands; private Command[] offCommands; public MedoControl(){ onCommands = new Command[5]; offCommands = new Command[5];
//这是一个空命令,里面的undo方法和execute方什么都不做. Command noCommand = new noCommand(); for(int i=0;i<onCommands.length;i++){ onCommands[i]=noCommand; offCommands[i]=noCommand; } } //这是初始化这个控制器,就是这个遥控器上有那些键,这些键给他设设置成什么命令.
//slot 表示那个键,每个键上对应什么命令 public void setCommand(int slot,Command on,Command off){ onCommands[slot]=on; offCommands[slot]=off; } @Override public void onButton(int slot) { onCommands[slot].execute(); } @Override public void offButton(int slot) { onCommands[slot].execute(); } }