简介
命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使得可以参数化客户端对象,队列化请求,以及支持可撤销的操作。
命令模式有以下角色:
命令 Command
命令式一个接口,定义了执行操作的方法 execute()
具体命令 ConcreteCommand
具体命令实现了命令接口,负责实际执行请求的操作。
调用者 lnvoker
调用者是客户端持有命令对象并调用命令对象的执行方法
接收者 receiver
接收者是命令的实际执行者,它知道如何执行与请求相关的操作
客户端 Client
客户端负责创建命令对象,并将命令对象与调用者进行关联
比如我们的车钥匙一般有三个按钮,上锁、开锁、开后备箱等等,车主拿出车钥匙,按下对应的按键,车就会执行对应的命令操作。
Demo
// Car Receiver 接收者接口
type Car interface {
Lock() // 上锁
Unlock() // 开锁
}
// Command 命令接口
type Command interface {
Execute()
}
// LockCommand 具体命令类:上锁命令
type LockCommand struct {
Car Car
}
func (c *LockCommand) Execute() {
c.Car.Lock()
}
type UnLockCommand struct {
Car Car
}
func (c *UnLockCommand) Execute() {
c.Car.Unlock()
}
// CarSystem ConcreteReceiver 具体接收者类:汽车
type CarSystem struct{}
func (c *CarSystem) Lock() {
fmt.Println("车门上锁")
}
func (c *CarSystem) Unlock() {
fmt.Println("车门解锁")
}
// CarOwner 调用者类:车主
type CarOwner struct {
Command Command
}
func (o *CarOwner) PressButton() {
o.Command.Execute()
}
测试
func TestCommand(t *testing.T) {
// 客户端使用命令模式
car := &CarSystem{}
// 创建具体命令对象
lockCommand := &LockCommand{Car: car}
unlockCommand := &UnLockCommand{Car: car}
// 创建调用者 车主
carOwner := &CarOwner{}
// 拿出钥匙,找到关锁按键
carOwner.Command = lockCommand
carOwner.PressButton() // 按下关锁按键
carOwner.Command = unlockCommand
carOwner.PressButton() // 按下开锁键
}
在这个例子中,Command 是命令接口,定义了一个 Execute() 方法。LockCommand、UnlockCommand 是具体命令类,分别表示上锁、开锁。Car 是接收者接口,定义了汽车的操作方法。CarSystem 是具体接收者类,实现了 Car 接口,表示汽车系统。CarOwner 是调用者类,持有一个命令对象,并通过 PressButton 方法来执行命令。
客户端通过创建具体的命令对象,并将这些命令对象与汽车系统关联,然后由车主来按下按钮执行不同的命令。这样,命令模式将操作和接收者解耦,使得车主可以方便地执行各种操作,同时也支持对命令进行扩展和组合。
作用和场景
很明显,一个作用就是解耦。我提都懒得提。
支持队列话请求
我们的例子没表现出来,但是命令模式可以将请求封装成命令对象,从而支持队列话请求,这样,可以按照一定的顺序执行一系列的命令,实现对请求的队列管理
支持命令的组合
可以通过组合多个命令对象来创建更复杂的命令,这样可以灵活的构建各种命令的组合,满足复杂的需求
支持队列化请求
令模式可以将请求封装成命令对象,从而支持队列化请求。这样,可以按照一定的顺序执行一系列的命令,实现对请求的队列管理。
当系统中的调用者和接收者之间存在紧密耦合关系,而需要解耦时,可以考虑使用命令模式。命令模式将请求封装成命令对象,使得调用者无需了解接收者的具体实现。