1. 基本概念
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或日志请求等方式来参数化其他对象。命令模式也支持可撤销的操作。
在命令模式中,有几个不同的角色,每个角色都有不同的职责和行为。以下是命令模式中的主要角色:
- Command(命令接口):
- 职责: 定义命令的接口,声明执行操作的方法
Execute
。 - 行为: 具体的命令类实现该接口,并负责实际执行操作。
- 职责: 定义命令的接口,声明执行操作的方法
- ConcreteCommand(具体命令):
- 职责: 实现
Command
接口,将请求绑定到一个接收者对象,并定义了执行请求的操作。 - 行为: 通常包含对接收者的引用,通过调用接收者的方法来执行具体的操作。
- 职责: 实现
- Invoker(调用者):
- 职责: 负责请求的发送者,即客户端与命令对象之间的中介。
- 行为: 将命令对象存储在内部,并在需要的时候调用命令的
Execute
方法。
- Receiver(接收者):
- 职责: 知道如何实施与请求相关的操作,它具体执行命令指定的操作。
- 行为: 实际执行操作的对象,是命令所作用的对象。
- Client(客户端):
- 职责: 创建命令对象和设置其接收者,与调用者对象关联。
- 行为: 创建具体的命令对象,并将其与相应的接收者关联,构建命令的执行链。
在一个典型的命令模式中,这些角色协同工作,通过将请求发送者和接收者解耦,使得系统更具灵活性和可扩展性。调用者不需要知道具体的命令执行细节,而是通过调用命令对象的Execute
方法来触发相应的操作。这样,可以轻松地添加新的命令和接收者,而无需修改现有的客户端代码。
2. 适用场景
- 当需要将请求发送者与接收者解耦时,使用命令模式将请求封装成一个对象。
- 当需要支持可撤销的操作时,可以使用命令模式来保存操作历史。
- 当需要支持事务性操作时,可以使用命令模式来将一系列操作组合成一个命令对象。
3. 优缺点
优点:
- 解耦发送者和接收者: 命令模式将请求发送者和接收者解耦,发送者不需要知道接收者的具体实现。
- 可扩展性: 可以很容易地添加新的命令类和接收者类,无需修改现有代码。
- 可撤销的操作: 命令模式支持可撤销的操作,通过保存历史命令可以实现撤销和重做功能。
缺点:
- 类数目增加: 可能会导致系统中类的数量增加,每个命令都需要一个具体的类。
- 复杂性增加: 对于简单的命令,可能引入过多的复杂性。
4. 示例
考虑一个简单的遥控器的例子,其中包含一组不同的命令按钮。每个按钮都可以执行不同的操作,例如打开电灯、关闭电灯等。使用命令模式,可以将每个操作封装成一个命令对象。
代码语言:go复制package main
import "fmt"
// Command Interface
type Command interface {
Execute()
}
// Receiver
type Light struct{}
func (l *Light) TurnOn() {
fmt.Println("Light is on")
}
func (l *Light) TurnOff() {
fmt.Println("Light is off")
}
// ConcreteCommand
type TurnOnCommand struct {
light *Light
}
func NewTurnOnCommand(light *Light) *TurnOnCommand {
return &TurnOnCommand{light: light}
}
func (c *TurnOnCommand) Execute() {
c.light.TurnOn()
}
// ConcreteCommand
type TurnOffCommand struct {
light *Light
}
func NewTurnOffCommand(light *Light) *TurnOffCommand {
return &TurnOffCommand{light: light}
}
func (c *TurnOffCommand) Execute() {
c.light.TurnOff()
}
// Invoker
type RemoteControl struct {
command Command
}
func (r *RemoteControl) SetCommand(command Command) {
r.command = command
}
func (r *RemoteControl) PressButton() {
r.command.Execute()
}
// Client
func main() {
light := &Light{}
turnOnCommand := NewTurnOnCommand(light)
turnOffCommand := NewTurnOffCommand(light)
remote := &RemoteControl{}
remote.SetCommand(turnOnCommand)
remote.PressButton()
remote.SetCommand(turnOffCommand)
remote.PressButton()
}
在这个示例中,Command
是命令接口,TurnOnCommand
和TurnOffCommand
是具体的命令类,Light
是接收者类,而RemoteControl
是调用者类。通过将命令封装成对象,可以轻松地添加新的命令和接收者类,实现了请求发送者和接收者的解耦。
我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开发者社区:孟斯特