一、命令模式概述
命令模式的定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(对象行为型)
- 命令模式优缺点:
- 优点:
- 1.类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command 抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
- 2.可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严 重的代码耦合。
- 3.命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题。
- 缺点:
- 如果有N个命令,问题就出来 了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大。
- 优点:
- 适用环境:
- 1.需要先将一个函数登记上,然后再以后调用此函数时,就需要使用命令模式,其实这就是回调函数
- 2.有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
二、代码实现
命令模式包含四个角色:
- Command命令角色(抽象):声明执行命令的接口,拥有执行命令的抽象方法 execute ();
- ConcreteCommand(具体命令):是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作;
- Invoker调用者角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
- Receiver接受者角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者;
2.1 抽象命令(Command接口)
package Command.remoteControl;
//命令接口
public interface Command {
//执行命令
public void execute();
}
2.2 具体命令(LightOnCommand、LightOffCommand、NoCommand、StereoOnWithCDCommand、StereoOffCommand)
package Command.remoteControl;
//具体命令,接受并执行命令,开灯命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light){
this.light = light;
}
@Override
public void execute() {
// TODO Auto-generated method stub
light.on();
}
}
package Command.remoteControl;
//具体命令,接受并执行命令,关灯
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();
}
}
package Command.remoteControl;
//具体命令,接受并执行命令,无任何响应命令
public class NoCommand implements Command {
@Override
public void execute() {
// TODO Auto-generated method stub
}
}
package Command.remoteControl;
//具体命令,接受并执行命令,开CD且音量为14
public class StereoOnWithCDCommand implements Command {
private Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
stereo.on();
stereo.setCD();
stereo.setVolume(14);
}
}
package Command.remoteControl;
//具体命令,接受并执行命令,关音响
public class StereoOffCommand implements Command {
private Stereo stereo;
public StereoOffCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
stereo.off();
}
}
2.3 Invoker(Light、Stereo)
package Command.remoteControl;
//Invoker,发送开关请求,电灯
public class Light {
String position;
public Light(String position) {
this.position = position;
}
public void on(){
System.out.println(position +" light is on...");
}
public void off(){
System.out.println(position+" light is off...");
}
}
package Command.remoteControl;
//Invoker,发送开关音量请求,音响
public class Stereo {
String position;
public Stereo(String position) {
this.position = position;
}
public void on(){
System.out.println(position + " stereo is on...");
}
public void off(){
System.out.println(position + " stereo is off...");
}
public void setCD() {
System.out.println(position+ " stereo is set for CD input...");
}
public void setVolume(int volume) {
System.out.println(position+" stereo volume set to " + volume);
}
}
2.4 接收者(RemoteControl)
package Command.remoteControl;
//Receiver:干活,遥控器
public class RemoteControl {
//开灯
private Command[] onCommands;
//关灯
private Command[] offCommands;
public RemoteControl(){
//初始化开与关的数组
onCommands = new Command[7];
offCommands = new Command[7];
NoCommand noCommand = new NoCommand();
for(int i=0;i<7;i++){
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
/**
* 设置按钮指令
* @param position
* @param onCommand
* @param offCommand
*/
public void setCommand(int position,Command onCommand, Command offCommand){
onCommands[position] = onCommand;
offCommands[position] = offCommand;
}
//按下开或关,硬件就负责调用对应的方法
public void onButtonWasPushed(int position) {
onCommands[position].execute();
}
public void offButtonWasPushed(int position) {
offCommands[position].execute();
}
public String toString() {
StringBuffer stringBuff = new StringBuffer();
stringBuff.append("\n------ Remote Control -------\n");
for (int i = 0; i < onCommands.length; i++) {
stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
+ " " + offCommands[i].getClass().getName() + "\n");
}
return stringBuff.toString();
}
}
2.5 main方法实现命令模式
package Command.remoteControl;
public class RemoteLoader {
public static void main(String[] args) {
// TODO Auto-generated method stub
RemoteControl remoteControl = new RemoteControl();
Light livingRoomLight = new Light("Living Room");
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
Stereo stereo = new Stereo("Living Room");
StereoOnWithCDCommand setreoOnWithCD = new StereoOnWithCDCommand(stereo);
StereoOffCommand setreoOff = new StereoOffCommand(stereo);
//加载到遥控器槽中
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, setreoOnWithCD, setreoOff);
//打印遥控器插槽和被指定的命令
System.out.println(remoteControl);
//按遥控器
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
}
}