命令模式:
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
命令模式的使用性:
1.抽象出待执行的动作以参数化某对象。
2.在不同的时刻指定、排列和执行请求。
3.支持取消操作
4.支持修改日志,这样当系统崩溃时,这样修改可以被重做一遍。
5.用构建在原语操作上的高层操作构造一个系统。
命令模式(Command)的应用效果:
1)command模式将调用操作的对象和实现该操作的对象解耦
2)可以将多个命令装配成一个复合命令,复合命令是Composite模式的一个实例
3)增加新的command很容易,无需改变已有的类
命令模式包含四种角色:
1.接收者Receriver :是一个类的实例,负责执行与请求相关的具体操作
2.命令接口Command:封装请求的若干个方法
3.具体命令ConcreteCommand: 实现命令接口的实例
4.请求者Invoker:是一个包含Command接口变量的类的实例。请求者负责调用具体命令,让具体命令执行哪些封装了请求的方法
命令模式经典UML类图
实例代码解析:
1.定义接收者Receiver:知道如何实现与执行一个请求相关的操作
package com.jdbc.receiver;
/**
* @ClassName: CellingFan
* @Description:接收者
* @author: lsh
* @date: 2019年5月21日
*/
public class CellingFan {
public static final int HIGH = 3;
public static final int MEDIUM = 2;
public static final int LOW = 1;
public static final int OFF = 0;
int speed; // 记录风扇的状态
public CellingFan() {
speed = OFF;
}
public void high() {
speed = HIGH;
System.out.println("风扇速度:高");
}
public void medium() {
speed = MEDIUM;
System.out.println("风扇速度:中");
}
public void low() {
speed = LOW;
System.out.println("风扇速度:低");
}
public void off() {
speed = OFF;
System.out.println("风扇速度:停");
}
public int getSpeed() {
return speed;
}
}
2.定义Command,声明执行操作的接口
package com.jdbc;
/**
* @ClassName: Command
* @Description:命令接口
* @author: lsh
* @date: 2019年5月21日
*/
public interface Command {
public void execute();
public void undo();
}
3.定义具体的命令ConcreteCommand,将一个接收者对象绑定于一个动作
package com.jdbc.concretecommand;
import com.jdbc.Command;
import com.jdbc.receiver.CellingFan;
/**
* @ClassName: CellingFanOffCommand
* @Description:具体命令1 ConcreteCommand:实现命令接口类的实例
* @author: lsh
* @date: 2019年5月21日
*/
public class CellingFanHighCommand implements Command {
// 持有接收者的应用,将一个接收对象绑定于一个动作
CellingFan cellingFan;
int preSpeed; // 记录之前的速度
public CellingFanHighCommand(CellingFan cellingFan) {
this.cellingFan = cellingFan;
}
@Override
public void execute() {
preSpeed = cellingFan.getSpeed();
cellingFan.high();
}
@Override
public void undo() {
if (preSpeed == CellingFan.HIGH) {
cellingFan.high();
}else if (preSpeed == CellingFan.MEDIUM) {
cellingFan.medium();
}else if (preSpeed == CellingFan.LOW) {
cellingFan.low();
}else if (preSpeed == CellingFan.OFF) {
cellingFan.off();
}
}
}
package com.jdbc.concretecommand;
import com.jdbc.Command;
import com.jdbc.receiver.CellingFan;
/**
* @ClassName: CellingFanOffCommand
* @Description:具体命令2 ConcreteCommand:实现命令接口类的实例
* @author: lsh
* @date: 2019年5月21日
*/
public class CellingFanOffCommand implements Command {
// 持有接收者的应用,将一个接收对象绑定于一个动作
CellingFan cellingFan;
int preSpeed; // 记录之前的速度
public CellingFanOffCommand(CellingFan cellingFan) {
this.cellingFan = cellingFan;
}
@Override
public void execute() {
preSpeed = cellingFan.getSpeed();
cellingFan.off();
}
@Override
public void undo() {
if (preSpeed == CellingFan.HIGH) {
cellingFan.high();
}else if (preSpeed == CellingFan.MEDIUM) {
cellingFan.medium();
}else if (preSpeed == CellingFan.LOW) {
cellingFan.low();
}else if (preSpeed == CellingFan.OFF) {
cellingFan.off();
}
}
}
4.定义Invoker,要求该命令执行这个请求。
package com.jdbc.Invoker;
import com.jdbc.Command;
import com.jdbc.concretecommand.NoCommand;
/**
* @ClassName: RemoteControl
* @Description:请求者
* @author: lsh
* @date: 2019年5月21日
*/
public class RemoteControl {
Command command;
public void setCommand(Command command) {
this.command = command;
}
public void buttonWasPushed() {
command.execute();
}
public void undoButtonWasPushed() {
command.undo();
}
}
5.测试:
package com.jdbc.client;
import com.jdbc.Invoker.RemoteControl;
import com.jdbc.concretecommand.CellingFanHighCommand;
import com.jdbc.concretecommand.CellingFanOffCommand;
import com.jdbc.receiver.CellingFan;
/**
* @ClassName: RemoteLoader
* @Description:TODO
* @author: lsh
* @date: 2019年5月22日
*/
public class RemoteLoader {
public static void main(String[] args) {
// 创建命令的接收者
CellingFan cellingFan = new CellingFan();
// 创建命令对象,并设定接受者
Command cellingFanOffCommand = new CellingFanOffCommand(cellingFan);
Command cellingFanHighCommand = new CellingFanHighCommand(cellingFan);
// 创建命令执行者
RemoteControl rc = new RemoteControl();
rc.setCommand(cellingFanHighCommand);
rc.buttonWasPushed();
rc.setCommand(cellingFanOffCommand);
rc.buttonWasPushed();
rc.undoButtonWasPushed();
}
}
测试结果如下: