命令模式(Command Pattern)是一种行为型设计模式,它将请求或操作封装成一个对象,从而允许您将客户端和接收者对象解耦。这种模式的主要目的是将请求发送者与接收者解耦,从而允许多种不同的请求来操作接收者对象,同时支持命令的撤销和重做。
以下是命令模式中涉及的关键角色:
命令模式的主要优点包括:
命令模式适用于许多不同的场景,特别是在需要将请求发送者与接收者解耦的情况下。以下是一些命令模式的常见使用场景:
总之,任何需要将请求或操作封装成对象,并支持撤销、重做、队列化、延迟执行等功能的情况都可以考虑使用命令模式。
以下是一个使用 Python 实现的简单命令模式示例,该示例模拟了遥控器控制电视的操作:
# 命令接口
class Command:
def execute(self):
pass
# 具体命令:打开电视
class TurnOnTVCommand(Command):
def __init__(self, tv):
self.tv = tv
def execute(self):
self.tv.turn_on()
# 具体命令:关闭电视
class TurnOffTVCommand(Command):
def __init__(self, tv):
self.tv = tv
def execute(self):
self.tv.turn_off()
# 接收者:电视
class Television:
def turn_on(self):
print("电视已打开")
def turn_off(self):
print("电视已关闭")
# 调用者:遥控器
class RemoteControl:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def press_button(self):
if self.command:
self.command.execute()
# 客户端代码
tv = Television()
turn_on_command = TurnOnTVCommand(tv)
turn_off_command = TurnOffTVCommand(tv)
remote = RemoteControl()
# 打开电视
remote.set_command(turn_on_command)
remote.press_button()
# 关闭电视
remote.set_command(turn_off_command)
remote.press_button()
在这个示例中:
在客户端代码中,我们创建了电视对象和两个具体的命令对象(打开电视和关闭电视),然后使用遥控器对象来执行这些命令。这样,遥控器和电视之间的交互被解耦,可以轻松添加新的命令和扩展功能。
+-------------------+
| Command |
+-------------------+
| + execute(): void |
+-------------------+
^
|
+----------------+-----------------+
| | |
+--------------+ +-----------------+ +-----------------+
| ConcreteCommand1 | | ConcreteCommand2 | | ConcreteCommand3 |
+--------------+ +-----------------+ +-----------------+
| + execute(): void | | + execute(): void | | + execute(): void |
+-------------------+ +-----------------+ +-----------------+
| |
| |
+-----------------+
| Invoker |
+-----------------+
| + setCommand(): void |
| + executeCommand(): void |
+-----------------+
^
|
+-----------------+
| Receiver |
+-----------------+
| + action(): void |
+-----------------+
在命令模式中,调用者(Invoker)不直接与接收者(Receiver)交互,而是通过命令对象来发出请求,这种解耦使得命令模式非常有用。
上述例子用Java语言实现示例如下:
// 命令接口
interface Command {
void execute();
}
// 具体命令:打开电视
class TurnOnTVCommand implements Command {
private Television tv;
public TurnOnTVCommand(Television tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.turnOn();
}
}
// 具体命令:关闭电视
class TurnOffTVCommand implements Command {
private Television tv;
public TurnOffTVCommand(Television tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.turnOff();
}
}
// 接收者:电视
class Television {
public void turnOn() {
System.out.println("电视已打开");
}
public void turnOff() {
System.out.println("电视已关闭");
}
}
// 调用者:遥控器
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
if (command != null) {
command.execute();
}
}
}
// 客户端代码
public class Main {
public static void main(String[] args) {
Television tv = new Television();
Command turnOnCommand = new TurnOnTVCommand(tv);
Command turnOffCommand = new TurnOffTVCommand(tv);
RemoteControl remote = new RemoteControl();
// 打开电视
remote.setCommand(turnOnCommand);
remote.pressButton();
// 关闭电视
remote.setCommand(turnOffCommand);
remote.pressButton();
}
}
上述例子用golang实现示例如下:
package main
import "fmt"
// Command 接口定义了命令的执行方法
type Command interface {
Execute()
}
// TurnOnTVCommand 具体命令:打开电视
type TurnOnTVCommand struct {
TV *Television
}
func (c *TurnOnTVCommand) Execute() {
c.TV.TurnOn()
}
// TurnOffTVCommand 具体命令:关闭电视
type TurnOffTVCommand struct {
TV *Television
}
func (c *TurnOffTVCommand) Execute() {
c.TV.TurnOff()
}
// Television 接收者:电视
type Television struct{}
func (tv *Television) TurnOn() {
fmt.Println("电视已打开")
}
func (tv *Television) TurnOff() {
fmt.Println("电视已关闭")
}
// RemoteControl 调用者:遥控器
type RemoteControl struct {
command Command
}
func (r *RemoteControl) SetCommand(command Command) {
r.command = command
}
func (r *RemoteControl) PressButton() {
if r.command != nil {
r.command.Execute()
}
}
func main() {
tv := &Television{}
turnOnCommand := &TurnOnTVCommand{TV: tv}
turnOffCommand := &TurnOffTVCommand{TV: tv}
remote := &RemoteControl{}
// 打开电视
remote.SetCommand(turnOnCommand)
remote.PressButton()
// 关闭电视
remote.SetCommand(turnOffCommand)
remote.PressButton()
}
上述例子用javascript实现示例如下:
// 命令接口
class Command {
execute() {}
}
// 具体命令:打开电视
class TurnOnTVCommand extends Command {
constructor(tv) {
super();
this.tv = tv;
}
execute() {
this.tv.turnOn();
}
}
// 具体命令:关闭电视
class TurnOffTVCommand extends Command {
constructor(tv) {
super();
this.tv = tv;
}
execute() {
this.tv.turnOff();
}
}
// 接收者:电视
class Television {
turnOn() {
console.log("电视已打开");
}
turnOff() {
console.log("电视已关闭");
}
}
// 调用者:遥控器
class RemoteControl {
constructor() {
this.command = null;
}
setCommand(command) {
this.command = command;
}
pressButton() {
if (this.command) {
this.command.execute();
}
}
}
// 客户端代码
const tv = new Television();
const turnOnCommand = new TurnOnTVCommand(tv);
const turnOffCommand = new TurnOffTVCommand(tv);
const remote = new RemoteControl();
// 打开电视
remote.setCommand(turnOnCommand);
remote.pressButton();
// 关闭电视
remote.setCommand(turnOffCommand);
remote.pressButton();
上述例子用C++实现如下:
#include
// 命令接口
class Command {
public:
virtual void execute() = 0;
};
// 具体命令:打开电视
class TurnOnTVCommand : public Command {
private:
Television* tv;
public:
TurnOnTVCommand(Television* tv) : tv(tv) {}
void execute() override {
tv->turnOn();
}
};
// 具体命令:关闭电视
class TurnOffTVCommand : public Command {
private:
Television* tv;
public:
TurnOffTVCommand(Television* tv) : tv(tv) {}
void execute() override {
tv->turnOff();
}
};
// 接收者:电视
class Television {
public:
void turnOn() {
std::cout << "电视已打开" << std::endl;
}
void turnOff() {
std::cout << "电视已关闭" << std::endl;
}
};
// 调用者:遥控器
class RemoteControl {
private:
Command* command;
public:
RemoteControl() : command(nullptr) {}
void setCommand(Command* cmd) {
command = cmd;
}
void pressButton() {
if (command) {
command->execute();
}
}
};
int main() {
Television tv;
TurnOnTVCommand turnOnCommand(&tv);
TurnOffTVCommand turnOffCommand(&tv);
RemoteControl remote;
// 打开电视
remote.setCommand(&turnOnCommand);
remote.pressButton();
// 关闭电视
remote.setCommand(&turnOffCommand);
remote.pressButton();
return 0;
}
使用命令模式创建一个简单的文本编辑器。该编辑器应具备以下功能:
要求:
你可以在评论区里或者私信我回复您的答案,这样我或者大家都能帮你解答,期待着你的回复~