目录
命令模式:
代码实例:
下面是面试中可能遇到的问题:
命令模式:
命令模式(Command Pattern)是一种行为型设计模式,它允许将请求封装成对象,从而让你能够用不同的请求对客户端进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
在命令模式中,通常包含以下几个角色:
-
Command(命令):命令的抽象类或接口,声明了执行命令的方法 execute()。
-
ConcreteCommand(具体命令):实现了 Command 接口的具体命令类,包含了执行命令所需的所有信息。
-
Invoker(调用者):发起执行命令的对象。
-
Receiver(接收者):命令的实际执行者。
-
Client(客户端):创建具体命令对象并设置接收者,然后将其传递给调用者进行执行。
代码实例:
下面是一个简单的 C++ 代码案例:
#include <iostream>
#include <vector>
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// 具体命令:开灯
class LightOnCommand : public Command {
public:
LightOnCommand() = default;
~LightOnCommand() override = default;
void execute() override {
std::cout << "Light is on" << std::endl;
}
};
// 具体命令:关灯
class LightOffCommand : public Command {
public:
LightOffCommand() = default;
~LightOffCommand() override = default;
void execute() override {
std::cout << "Light is off" << std::endl;
}
};
// 调用者:遥控器
class RemoteControl {
public:
void setCommand(Command* cmd) {
m_command = cmd;
}
void buttonPressed() {
m_command->execute();
}
private:
Command* m_command;
};
// 客户端
int main() {
RemoteControl remote;
LightOnCommand lightOn;
LightOffCommand lightOff;
remote.setCommand(&lightOn); // 设置开灯命令
remote.buttonPressed(); // 按下按钮,执行开灯命令
remote.setCommand(&lightOff); // 设置关灯命令
remote.buttonPressed(); // 按下按钮,执行关灯命令
return 0;
}
在上面的代码中,Command 是命令的抽象类,LightOnCommand 和 LightOffCommand 是具体命令。RemoteControl 是调用者,用于设置和执行命令。客户端创建具体命令对象并设置接收者,然后将其传递给调用者进行执行。
当客户端执行 remote.buttonPressed() 时,将会调用当前设置的具体命令对象的 execute() 方法,从而实现命令的执行。这种方式可以将命令的执行和接收者对象解耦,从而实现请求的可替换性和扩展性。同时,它还支持撤销和重做等操作。
下面是面试中可能遇到的问题:
- 1你能解释一下命令模式吗?
答:命令模式是一种行为型设计模式,它将请求或操作封装为对象,以便于参数化、记录请求、队列请求或撤销操作等。它分为几个角色:Command(命令)、ConcreteCommand(具体命令)、Invoker(调用者)、Receiver(接收者)和 Client(客户端)。
- 2你能举一个命令模式的例子吗?
答:比如,我们可以通过命令模式实现一个遥控器控制家庭电器的功能。其中,遥控器就是 Invoker,每个电器(如电视、音响、灯)都对应一个 ConcreteCommand。这些 ConcreteCommand 对象将执行电器的操作,并将其封装为一个命令对象。当遥控器按下按钮时,它将调用该命令对象的 execute() 方法,从而实现对电器的控制。
- 3命令模式与策略模式有什么区别?
答:命令模式和策略模式都属于行为型模式,但它们的目的不同。命令模式的目的是将请求或操作封装为对象,以便于参数化、记录请求、队列请求或撤销操作等。而策略模式的目的是允许在运行时动态地改变对象的行为。在命令模式中,客户端不知道命令的接收者是谁,而在策略模式中,客户端通常知道策略对象的存在,并在运行时决定使用哪个策略对象。
- 4在命令模式中,什么是 Invoker?
答:Invoker 是调用者,它负责将命令对象传递给具体的接收者并执行命令。Invoker 通常包含一个 setCommand() 方法,用于设置具体的命令对象,并包含一个 buttonPressed() 方法,用于执行命令。Invoker 可以被认为是客户端与命令模式的桥梁,它将客户端与命令对象解耦,从而实现请求的可替换性和扩展性。
- 5在命令模式中,什么是 Receiver?
答:Receiver 是接收者,它负责执行 ConcreteCommand 对象所包含的操作。在命令模式中,每个 ConcreteCommand 都对应一个 Receiver 对象,而 Client 不直接调用 Receiver,而是通过 Command 和 Invoker 与 Receiver 通信。
- 6在命令模式中,什么是 Command?
答:Command 是命令,它定义了一个操作的接口,具体的命令都需要实现该接口。Command 接口通常包含一个 execute() 方法,该方法用于执行 ConcreteCommand 对象所包含的操作。
- 7在命令模式中,什么是 ConcreteCommand?
答:ConcreteCommand 是具体的命令,它实现了 Command 接口,并包含了一个 Receiver 对象。ConcreteCommand 对象将 Receiver 对象封装到一个命令对象中,并实现了 execute() 方法,该方法用于调用 Receiver 对象的方法。
- 8在命令模式中,什么是 Client?
答:Client 是客户端,它负责创建 ConcreteCommand 对象并将其传递给 Invoker 对象。Client 不知道命令的接收者是谁,它只关心将请求发送给 Invoker 对象即可。
- 9你觉得命令模式的优点有哪些?
答:命令模式的优点包括:
- 降低系统的耦合度,将请求发送者和接收者解耦。
- 可以很容易地实现撤销、重做等操作,以及记录请求日志等操作。
- 可以很方便地实现队列、延迟执行等功能。
- 可以很方便地扩展命令的功能,只需要增加新的 ConcreteCommand 对象即可。
- 20在实际项目中,你是否使用过命令模式?可以举一个例子吗?
答:是的,我在一个电商网站的订单处理系统中使用了命令模式。在该系统中,每个订单都对应一个 ConcreteCommand 对象,该对象包含了一个 Receiver 对象,并实现了 execute() 方法,用于执行订单处理逻辑。当用户下订单时,Client 会创建一个 ConcreteCommand 对象,并将其传递给 Invoker 对象,从而实现订单的处理。该系统的优点是,它可以方便地记录订单的处理日志,并支持撤销和重做操作。