定义:
把“请求”封装成对象,以便使用不同的请求、 队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。
类图:
角色:
command:定义了命令的接口,声明了执行的方法
concreteCommand:接口的实现方式,一般会持有接收者,调用接收者完成指令,也可以充当接受者
receiver:接受者,真正执行命令的实体,任何类都可能成为接受者,只要能够完成相应的功能
Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
优点:
1.降低耦合程度
2.容易扩展,新增一个命令到系统中
3.使得组合更加方便
缺点:
肯能会导致过多的命令类,因为针对每一个命令都需要一个具体的命令类
例子:
开灯和关灯的例子
command:
public interface Command { public void execute(); }
concreteCommand:
public class LightOffCommand implements Command { Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.off(); } }
public class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } }
receiver:
public class Light { public void on(){ System.out.println("light on ... "); } public void off(){ System.out.println("light off ..."); } }Invoker:
public class SimpleRemoteControl { Command slot; public void setCommand(Command command){ this.slot = command; } public void buttonWasPress(){ slot.execute(); } }
Client:
public class SimpleRemoteControlTest { public static void main(String[] args) { SimpleRemoteControl remote = new SimpleRemoteControl(); Light light = new Light(); LightOnCommand lightOn = new LightOnCommand(light); remote.setCommand(lightOn); remote.buttonWasPress(); LightOffCommand lightOff = new LightOffCommand(light); remote.setCommand(lightOff); remote.buttonWasPress(); } }
总结
1.命令模式的本质是对命令进行了封装,把命令的发出者和命令的执行者分隔开来。
2. 每一个命令对应着一个操作,发出命令方请求一个操作,而执行命令方,接到对应的请求进行执行。
3. 命令模式分割开了请求方和执行方,屏蔽了执行方的细节,少暴露 类内部的信息。
4. 命令模式 面向接口编程,更容易扩展