go语言设计模式 - 命令模式 | 青训营笔记

88 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天

go语言设计模式 - 命令模式

1. 介绍

将请求封装成一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

2. 类图

image-20230125163555623

Command(抽象方法类): 抽象命令一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。

ConcreteCommand(具体命令类): 具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action).

Invoker(调用者): 调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接受者,因此它至于抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接受者的相关操作。

Receiver(接收者): 接收者执行与请求相关的操作,它具体实现对请求的业务处理。

3. 代码实现

package main
​
import "fmt"type Doctor struct{}
​
func (d *Doctor) TreatEye() {
    fmt.Println("医生治疗眼睛")
}
​
func (d *Doctor) TreateNose() {
    fmt.Println("医生治疗鼻子")
}
​
// 抽象的命令
type Command interface {
    Treat()
}
​
// 治疗眼睛的病单
type CommandTreatEye struct {
    doctor *Doctor
}
​
func (cmd *CommandTreatEye) Treat() {
    cmd.doctor.TreatEye()
}
​
// 治疗鼻子的病单
type CommandTreatNose struct {
    doctor *Doctor
}
​
func (cmd *CommandTreatNose) Treat() {
    cmd.doctor.TreateNose()
}
​
// 护士 命令的调用者
type Nurse struct {
    CmdList []Command // 收集的命令集合
}
​
// 业务层
func (n *Nurse) Notify() {
    if n.CmdList == nil {
        return
    }
​
    for _, cmd := range n.CmdList {
        cmd.Treat()
    }
}
​
// 病人 业务层
func main() {
    // 依赖病单 通过填写病单 让医生看病
    doctor := new(Doctor)
    cmdEye := CommandTreatEye{doctor: doctor}
    cmdNose := CommandTreatNose{doctor: doctor}
​
    // 护士
    nurse := new(Nurse)
​
    // 收集管理病单
    nurse.CmdList = append(nurse.CmdList, &cmdEye, &cmdNose)
​
    // 诊断
    nurse.Notify()
}
​

4. 适用场景

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无需知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
  2. 系统需要再不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以由不同的生命期,换言之,最初的请求发出者可能已经不存在了,而命令对象本身仍然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志等机制来具体实现。
  3. 系统需要将一组操作组合在一起形成宏命令。