Go 设计模式- 命令模式

327 阅读2分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

命令模式

命令模式本质上是把对象的方法调用封装到对象中,方便传递、存储和调用。

命令模式是行为型设计模式的一种,目的是将调用操作的对象解耦,增加新的命令不影响现有的类。

命令模式是集那个请求封装成一个对象,使得我们可以用不同的请求进行参数化,

命令模式中的角色

  • Command: 命令
  • Invoker: 调用者
  • Recevier: 接收者
  • Client: 客户端
  • ConcreteCommand: 命令具体实现

客户端通过调用者发送命令,命令接受者执行相关操作。

请求步骤如下:

  1. 客户端 Client 创建一个 ConcreteCommand 对象并且制定它的 Receiver 对象
  2. Invoker 对象设置 ConcreteCommand 对象
  3. Invoker 通过调用 Command 的 Execute 操作提交一个请求。
  4. ConcreteCommand 对象调用 Receiver 的一些操作执行该请求。

image.png

将函数作为一个参数传递给另外一个函数

package command

import (
   "fmt"
   "testing"
)

func Func(i func(int, int) int) int {
   fmt.Printf("i type: %T\n", i)
   return i(3, 2)
}

func TestFunc(t *testing.T) {
   add := func(x, y int) int {
      return x + y
   }
   fmt.Printf("add type: %T\n", add)
   fmt.Println(Func(add))
}

执行结果:

=== RUN   TestFunc
add type: func(int, int) int
i type: func(int, int) int
5
--- PASS: TestFunc (0.00s)
PASS

命令模式代码实现

命令接口

type Command interface {
   Execute()
}

命令接口具体实现代码


// 命令接口的具体实现
type onCommand struct {
   device device
}

func (c *onCommand) Execute() {
   c.device.on()
}

type offCommand struct {
   device device
}

func (c *offCommand) Execute() {
   c.device.off()
}

接收者接口

// 接收者接口
type device interface {
   on()
   off()
}

接收者接口的具体实现

// 接收者的具体实现
type tv struct {
   isRunning bool
}

func (t *tv) on() {
   t.isRunning = true
   fmt.Println("Turning tv on")
}

func (t *tv) off() {
   t.isRunning = false
   fmt.Println("Turning tv off")
}

调用者接口

// 请求者(调用者)具体实现 调用者 Invoker
type button struct {
   command Cmd
}

func (b *button) press() {
   b.command.Execute()
}

测试代码


// 客户端
// 0. Receiver 对象
tv := &tv{

}

//  1. 客户端 Client 创建一个 ConcreteCommand 对象并且制定它的 Receiver 对象
onCmd := &onCommand{device: tv}

offCmd := &offCommand{
   device: tv,
}

// 2. Invoker 对象设置 ConcreteCommand 对象
onButton := &button{
   command: onCmd,
}
onButton.press()

offButton := &button{
   command: offCmd,
}
offButton.press()

执行结果:

=== RUN   TestExampleCommand
Turning tv on
Turning tv off
--- PASS: TestExampleCommand (0.00s)
PASS