定义
将“请求”封装成对象,以便使用不同的请求、队列或者日志类参数化其他对象。命令模式也可以支持撤销的操作。
要点
1、命令模式将发出的请求和执行请求的对象进行解耦。
2、在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接收者的一个或一组动作
3、调用者通过命令对象的execute()发出请求,这会使得接收者的动作被调用。
4、调用者可以接受命令当做参数,甚至在运行时动态的进行
用途
1、命令模式将发出请求的对象和执行请求的对象进行解耦
2、用于队列请求,命令对象和一般对象一样可以被传来传去,只要实现统一的接口方法,可以被任意调用
3、用于日志请求,将所有动作记录在日志中,以便系统死机后能够重新调用来恢复
参与对象
1、调用者:用来发送请求的对象
2、接收者:接受请求实际执行一组动作的对象
3、命令对象:在调用者和接收者间充当解耦的角色,将调用者和接收者结合起来
举例应用
有一个遥控器,还有电灯、电风扇、空调等电器,要实现遥控器可以随意切换执行对这些电器的遥控。
进行抽象
1、调用者:遥控器
2、接收者:电器
3、命令对象
类图
具体实现
电器:
Light:
public class Light {
private String location;
public Light(String location) {
this.location = location;
}
public void on() {
System.out.println(location + "电灯打开");
}
public void off() {
System.out.println(location + "电灯关闭");
}
}
Fridge:
public class Fridge {
private String location;
public Fridge(String location) {
this.location = location;
}
public void on() {
System.out.println(location + "冰箱打开");
}
public void off() {
System.out.println(location + "冰箱关闭");
}
}
CellingFan:
public class CellingFan {
private String location;
public CellingFan(String location) {
this.location = location;
}
public void high(){
System.out.println(location +"的电风扇开启高档");
}
public void medium(){
System.out.println(location +"的电风扇开启中档");
}
public void low(){
System.out.println(location +"的电风扇开启低挡");
}
public void off(){
System.out.println(location +"的电风扇关闭");
}
}
Command(命令对象接口)
public interface Command {
void execute();
}
具体命令对象:
LightOffCommand:
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
LightOnCommand:
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
FridgeOnCommand:
public class FridgeOnCommand implements Command {
private Fridge fridge;
public FridgeOnCommand(Fridge fridge) {
this.fridge = fridge;
}
@Override
public void execute() {
fridge.on();
}
}
FridgeOffCommand:
public class FridgeOffCommand implements Command {
private Fridge fridge;
public FridgeOffCommand(Fridge fridge) {
this.fridge = fridge;
}
@Override
public void execute() {
fridge.off();
}
}
CellingFanOnCommand:
public class CellingFanOnCommand implements Command {
private CellingFan cellingFan;
public CellingFanOnCommand(CellingFan cellingFan) {
this.cellingFan = cellingFan;
}
@Override
public void execute() {
cellingFan.high();
}
}
CellingFanOffCommand:
public class CellingFanOffCommand implements Command{
private CellingFan cellingFan;
public CellingFanOffCommand(CellingFan cellingFan) {
this.cellingFan = cellingFan;
}
@Override
public void execute() {
cellingFan.off();
}
}
RemoteControl(遥控器):
public class RemoteControl {
private Command onCommand;
private Command offCommand;
public void setOnCommand(Command onCommand) {
this.onCommand = onCommand;
}
public void setOffCommand(Command offCommand) {
this.offCommand = offCommand;
}
public void on(){
onCommand.execute();
}
public void off(){
offCommand.execute();
}
public static void main(String[] args) {
RemoteControl rc = new RemoteControl();
Light light = new Light("客厅");
LightOnCommand lightOnCommand = new LightOnCommand(light);
LightOffCommand lightOffCommand = new LightOffCommand(light);
rc.setOffCommand(lightOffCommand);
rc.setOnCommand(lightOnCommand);
rc.on();
rc.off();
}
}
---
客厅电灯打开
客厅电灯关闭
如果直接使用Light、Fridge、CellingFan等直接命令执行者放在RemoteControl中,可以使用if...else...
来实现,但是增加新的电器,那么就要修改RemoteControl代码
而通过实现Command接口的命令对象,可以进行完美解耦。
总结:
当需要将发出请求的对象和执行请求的对象进行解耦的时候,则可以用到命令模式。