[8] [行为变化] ( 1 ) 命令模式 command
总结
-
GOF定义?
将一个请求(行为)封装为一个对象,
从而使你可用不同的请求对客户进行参数化操作.
比如请求排队, 记录请求日志, 撤销...
(请求一旦变成对象就具有了很高的灵活度)
-
该模式的目的是什么?
解耦 Invoker请求方 和 Receiver行为实现者
(RemoteControl 和 Light子类)
-
如何达成目的?
把行为封装成对象
(把Receiver行为实现者封装成Command对象)
-
命令模式的优点?
请求(行为)可以被更灵活的处理
(1) 当做方法参数传递
(2) 延迟执行
(3) 排队执行
(4) 可撤销操作
-
场景举例?
文本编辑器
图形编辑器
-
Command模式和c++函数对象的区别?
Command模式是运行时多态. (通过接口规范实现, 更加严格, 但虚函数有性能损失)
C++函数对象是编译时多态. (通过模板实现的泛型编程, 性能更好)
-
补充参考资料
https://blog.csdn.net/A_art_xiang/article/details/130706288
java例子
重构前
Invoker请求方(LightController1)和Receiver行为实现者(Light子类)紧耦合.
package v23_command.java;
interface Light {
void on();
void off();
}
class LivingRoomLight implements Light {
public void on() {
System.out.println("Living room light is on");
}
public void off() {
System.out.println("Living room light is off");
}
}
class KitchenLight implements Light {
public void on() {
System.out.println("Kitchen light is on");
}
public void off() {
System.out.println("Kitchen light is off");
}
}
public class LightController1 {
public static void main(String[] args) {
LivingRoomLight livingRoomLight = new LivingRoomLight();
KitchenLight kitchenLight = new KitchenLight();
kitchenLight.on();
kitchenLight.off();
livingRoomLight.on();
livingRoomLight.off();
}
}
重构后
package v23_command.java;
import java.util.Arrays;
import java.util.List;
interface Light {
void on();
void off();
void increaseBrightness();
}
class KitchenLight implements Light {
public void on() {
System.out.println("Kitchen light is on");
}
public void off() {
System.out.println("Kitchen light is off");
}
public void increaseBrightness() {
System.out.println("Kitchen light brightness increased");
}
}
class LivingRoomLight implements Light {
public void on() {
System.out.println("Living room light is on");
}
public void off() {
System.out.println("Living room light is off");
}
public void increaseBrightness() {
System.out.println("Living room light brightness increased");
}
}
interface Command {
void execute();
void undo();
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
public void undo() {
light.off();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
public void undo() {
light.on();
}
}
class LightIncreaseCommand implements Command {
private Light light;
public LightIncreaseCommand(Light light) {
this.light = light;
}
public void execute() {
light.increaseBrightness();
}
public void undo() {
// Implement an appropriate undo operation, such as decreasing brightness
System.out.println("TODO");
}
}
class Fan {
public void on() {
System.out.println("Fan is on");
}
public void off() {
System.out.println("Fan is off");
}
}
class FanOnCommand implements Command {
private Fan fan;
public FanOnCommand(Fan fan) {
this.fan = fan;
}
public void execute() {
fan.on();
}
public void undo() {
fan.off();
}
}
class AllLightsOffCommand implements Command {
private List<Light> lights;
public AllLightsOffCommand(List<Light> lights) {
this.lights = lights;
}
public void execute() {
for (Light light : lights) {
light.off();
}
}
public void undo() {
for (Light light : lights) {
light.on();
}
}
}
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
public class LightController3 {
public static void main(String[] args) {
LivingRoomLight livingRoomLight = new LivingRoomLight();
KitchenLight kitchenLight = new KitchenLight();
Fan fan = new Fan();
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
LightIncreaseCommand kitchenLightIncrease = new LightIncreaseCommand(kitchenLight);
FanOnCommand fanOn = new FanOnCommand(fan);
AllLightsOffCommand allLightsOff = new AllLightsOffCommand(Arrays.asList(
livingRoomLight, kitchenLight));
RemoteControl remote = new RemoteControl();
remote.setCommand(livingRoomLightOn);
remote.pressButton(); // Living room light is on
remote.pressUndo(); // Living room light is off
remote.setCommand(kitchenLightOff);
remote.pressButton(); // Kitchen light is off
remote.pressUndo(); // Kitchen light is on
remote.setCommand(kitchenLightIncrease);
remote.pressButton(); // Increase kitchen light brightness
remote.setCommand(fanOn);
remote.pressButton();
remote.setCommand(allLightsOff);
remote.pressButton();
}
}


java例子2
package v23_command.java;
import java.util.Stack;
interface Command {
void execute();
void undo();
}
class InsertTextCommand implements Command {
private String textToInsert;
private StringBuilder textEditor;
private int position;
public InsertTextCommand(String text, StringBuilder editor, int position) {
this.textToInsert = text;
this.textEditor = editor;
this.position = position;
}
@Override
public void execute() {
textEditor.insert(position, textToInsert);
}
@Override
public void undo() {
textEditor.delete(position, position + textToInsert.length());
}
}
class DeleteTextCommand implements Command {
private String deletedText;
private StringBuilder textEditor;
private int position;
public DeleteTextCommand(StringBuilder editor, int position, int length) {
this.textEditor = editor;
this.position = position;
this.deletedText = textEditor.substring(position, position + length);
}
@Override
public void execute() {
textEditor.delete(position, position + deletedText.length());
}
@Override
public void undo() {
textEditor.insert(position, deletedText);
}
}
class CommandInvoker {
Stack<Command> commandStack = new Stack<>();
Stack<Command> undoStack = new Stack<>();
public void execute(Command command) {
command.execute();
commandStack.push(command);
}
public void undo() {
if (!commandStack.isEmpty()) {
Command command = commandStack.pop();
command.undo();
undoStack.push(command);
}
}
public void redo() {
if (!undoStack.isEmpty()) {
Command command = undoStack.pop();
command.execute();
commandStack.push(command);
}
}
}
public class TextEditor {
public static void main(String[] args) {
// Initialize the text editor and invoker
StringBuilder textEditor = new StringBuilder();
CommandInvoker invoker = new CommandInvoker();
// Insert "Hello, "
invoker.execute(new InsertTextCommand("Hello, ", textEditor, 0));
// Insert "world!"
invoker.execute(new InsertTextCommand("world!", textEditor, 7));
// Delete ", "
invoker.execute(new DeleteTextCommand(textEditor, 5, 2));
// Current text should be "Helloworld!"
System.out.println("Current text: " + textEditor.toString());
invoker.undo(); // Undo delete - should be back to "Hello, world!"
System.out.println("After undo: " + textEditor.toString());
invoker.undo(); // Undo last insert - should be back to "Hello, "
System.out.println("After undo: " + textEditor.toString());
invoker.redo(); // Redo last insert - should be back to "Hello, world!"
System.out.println("After redo: " + textEditor.toString());
}
}

浙公网安备 33010602011771号