我们都熟悉电视遥控器,它有许多按钮,每个按钮都有确定的功能。你按下电源键电视就会打开,再按下一次电视就会关闭。编程世界里也有这种模式,这就是我们说的命令模式。
命令模式是一种设计模式,它把一个请求或操作封装到一个对象中。这意味着命令模式允许我们将操作分开,我们可以控制何时和如何执行它们。
了解命令模式的最好方式,就是通过代码来看看它如何运作。
假设我们要制作一个游戏模拟器,运行器可以执行两个命令,启动和关闭。
// 游戏模拟器操作接口
interface Command {
void execute();
}
class GameConsole {
public void start_game() {
System.out.println("游戏开启!");
}
public void stop_game() {
System.out.println("游戏关闭!");
}
}
// 启动命令
class StartCommand implements Command {
GameConsole console;
public StartCommand(GameConsole console) {
this.console = console;
}
public void execute() {
console.start_game();
}
}
// 停止命令
class StopCommand implements Command {
GameConsole console;
public StopCommand(GameConsole console) {
this.console = console;
}
public void execute() {
console.stop_game();
}
}
// 游戏模拟器
class GameSimulator {
HashMap commands = new HashMap<>();
public void register(String cmd_name, Command command) {
commands.put(cmd_name, command);
}
public void execute(String cmd_name) {
if (commands.containsKey(cmd_name)) {
Command command = commands.get(cmd_name);
command.execute();
} else {
System.out.println("Unknown command!");
}
}
}
public class Main {
public static void main(String[] args) {
GameSimulator simulator = new GameSimulator();
GameConsole console = new GameConsole();
simulator.register("START", new StartCommand(console));
simulator.register("STOP", new StopCommand(console));
simulator.execute("START");
simulator.execute("STOP");
}
}
在上面的Java代码中,我们创建了一个游戏模拟器,它可以执行两种命令:启动和停止。我们使用了接口来定义Command,它只有一个execute方法。然后,我们创建了两个Command的实现类,即启动命令(StartCommand)和停止命令(StopCommand)。
撤销和恢复的操作是通过以下两步实现的:
让我们来看一个Java代码例子,这个例子展示了如何使用命令模式实现撤销功能:
interface Command {
void execute();
void undo();
}
class AddTextCommand implements Command {
private String textToAdd;
private TextEditor editor;
public AddTextCommand(String textToAdd, TextEditor editor) {
this.textToAdd = textToAdd;
this.editor = editor;
}
public void execute() {
editor.addText(textToAdd);
}
public void undo() {
editor.removeText(textToAdd);
}
}
class TextEditor {
private StringBuilder text = new StringBuilder();
public void addText(String textToAdd) {
text.append(textToAdd);
}
public void removeText(String textToRemove) {
int index = text.lastIndexOf(textToRemove);
if (index != -1) {
text.delete(index, index + textToRemove.length());
}
}
public void printText() {
System.out.println(text.toString());
}
}
class TextEditorDriver {
private Stack commandHistory = new Stack<>();
public void executeCommand(Command cmd) {
cmd.execute();
commandHistory.push(cmd);
}
public void undoLastCommand() {
if (!commandHistory.isEmpty()) {
Command lastCmd = commandHistory.pop();
lastCmd.undo();
}
}
}
在这段代码中,我们首先定义了一个Command接口,并添加了一个新的方法undo。我们的每个具体命令都必须定义这两个方法。
在TextEditorDriver类中,我们维护了一个命令历史stack。每次执行命令时,我们都将命令添加到这个stack中。当我们要撤销操作时,我们只需取出最新的命令,并调用它的undo方法。
在命令模式中,撤销和恢复功能的实现核心是在每个具体的命令中,都保存了足够的信息以便在需要时可以反转其效果。通过使用存储的命令历史,我们不仅可以撤销命令,还可以重做它们。
以上的小例子虽然简单,但是已经显示了命令模式的三大优点:
命令模式是创建型和行为型设计模式的交织,使用它,你就可以变得像使用遥控器一样自由自在地控制你的代码。
我们之前提到命令模式是创建型和行为型设计模式的交织。那么这句话是怎么理解的呢?
设计模式通常被分为三种类型:创建型,结构型和行为型。
命令模式是一个行为型模式,因为它解决的主要问题是将行为请求者和接收者进行解耦,实现请求的封装。这让请求者不必知道接收者的接口,也不必知道请求是怎么被接收的,以及操作是否被执行、是如何执行的,等等。
不过,命令模式也涉及创建型模式的一些特性:它涉及到具体命令类的创建以及如何和特定接收者实例相关联。每个具体的命令类都封装了特定的行为和调用接收者的相应方法。这样,每个命令可以看作是一个完整的操作。
因此,命令模式是创建型模式和行为型模式的交织。它是创建型的,因为它创建了具有特定行为的命令对象。同时它是行为型的,因为这些对象被调用来执行特定的行为。
理解和从实际角度看待设计模式非常重要,因为它们是我们进行有效编程和设计灵活可维护系统的工具。希望这次的讨论能帮助你更好地理解命令模式,明白它是如何综合创建型模式和行为型模式的。
当然,设计模式并不是银弹,应当根据具体场景和需求采取合适的设计模式。而这个能力则需要大量实践和经验的积累,加油!
如果上面的内容对你有帮助,请点赞收藏哦,我会分享更多的经验~