命令模式(Command Pattern)
首先要理解什么是命令,命令就是通过目标的引用去调用目标的方法,所以命令的发出者必须有目标的引用。代码上就是点操作符访问咯,object.method(param...)。
而命令模式的意图就是,将这个方法的调用过程封装起来,封装为一个对象,这个对象就叫做命令,有封装就肯定有抽象才显得有逼格啊。这样就将发出者和目标的 调用关系 解耦了。所以抽象命令里肯定就有目标类的抽象父类啦,而命令发出者就肯定有抽象命令啦,而具体的执行肯定就是具体命令类里面有具体目标类啦。
所以就是:命令放出者(内含抽象命令)--> 抽象命令(内含抽象目标)--> 具体命令(内含具体目标)--> 实例化时发出者动态绑定具体命令对象。
命令模式的缺点是:可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。
命令模式的定义:
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
即将目标的抽象作为抽象命令中方法的参数,也就是参数化目标。
命令模式包含以下主要角色。
- 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
- 具体命令(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
抽象命令类(Command)角色:
package s_interface;
/**
* 命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
* 这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
*
* 请求的意思是:调用者在内部“通过接收者的引用 调用接收者的方法”,这个过程也就是请求的过程,也是调用者发出了一个命令,命令的具体内容是在接收者中的代码定义的。
*
* 所以封装一个命令其实是封装一个过程,把命令“发出”到“接收”的过程封装起来,而不是把命令的具体内容封装起来,别理解错了。
*
* 所以,肯定会涉及到多态的,命令过程的封装,就要包含了接受者的引用了,但是肯定不能固定死该引用,于是就要多一层接口的抽象,使得命令可以适配任何接收者。
*
* 于是适配了某个具体接收者引用的命令就是具体命令,而上一层则是抽象命令,明显发送者是通过调用上层抽象通过多态调用到具体命令的具体接收者的方法来执行命令的。
*
* 于是,我们就把调用者直接绑定接收者的引用这个耦合解耦出来了,更具有灵活性了。调用者只需要关系抽象命令接口,而不需要关心具体的接收者是谁,留给命令对象去关心就好。
*
* 所以,我们就要在具体命令对象的代码里面设计接收者引用这些耦合代码了咯。一个具体命令耦合一个具体的接受者(多态也行)。
*
* @author mathew
*
*/
public interface Command {
public void excute();
}
具体命令类(Concrete Command)角色:
package s_impClass;
import s_interface.Command;
import s_receiverClass.Light;
/**
* 具体的命令过程封装,开灯的命令
* @author mathew
*
*/
public class LightOnCommand implements Command {
//接收者的引用
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void excute() {
// TODO Auto-generated method stub
light.on();
}
}
实现者/接收者(Receiver)角色:
package s_receiverClass;
/**
* 命令的目标,具体接收者,灯
* @author mathew
*
*/
public class Light {
public void on() {
System.out.println("打开灯,Linght On !!");
}
public void off() {
System.out.println("关闭灯,Linght Off !!");
}
}
调用者/请求者类(Invoker)角色:
package s_invokerClass;
import s_interface.Command;
/**
*命令的发出者,调用者,遥控器
* @author mathew
*
*/
public class SimpleRemote {
//命令的抽象
private Command slot;
public SimpleRemote() {}
//提供接口给用户设置命令
public void setCommand(Command command) {
this.slot = command;
}
//多态调用命令,也就是调用命令
public void buttonWasPressed() {
//多态调用
slot.excute();
}
}