命令模式

命令模式

定义:命令模式将请求(命令)封装为一个对象,可以使用不同的请求参数化其他对象(将不同请求注入到其他对象),冰能够支持请求(命令)的排队执行,记录日志,撤销等(附加控制)功能

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

// Package command 命令模式
// 这是示例二,采用将直接返回一个函数,不用对象
// 示例说明:
// 假设现在有一个游戏服务,我们正在实现一个游戏后端
// 使用一个 goroutine 不断接收来自客户端请求的命令,并且将它放置到一个队列当中
// 然后我们在另外一个 goroutine 中来执行它
package command

import "fmt"


// ICommand 命令
type ICommand interface {
Execute() error
}

// StartCommand 游戏开始运行
type StartCommand struct{}

// NewStartCommand NewStartCommand
func NewStartCommand( /*正常情况下这里会有一些参数*/ ) *StartCommand {
return &StartCommand{}
}

// Execute Execute
func (c *StartCommand) Execute() error {
fmt.Println("game start")
return nil
}

// ArchiveCommand 游戏存档
type ArchiveCommand struct{}

// NewArchiveCommand NewArchiveCommand
func NewArchiveCommand( /*正常情况下这里会有一些参数*/ ) *ArchiveCommand {
return &ArchiveCommand{}
}

// Execute Execute
func (c *ArchiveCommand) Execute() error {
fmt.Println("game archive")
return nil
}


// Command 命令
type Command func() error

// StartCommandFunc 返回一个 Command 命令
// 是因为正常情况下不会是这么简单的函数
// 一般都会有一些参数
func StartCommandFunc() Command {
return func() error {
fmt.Println("game start")
return nil
}
}

// ArchiveCommandFunc ArchiveCommandFunc
func ArchiveCommandFunc() Command {
return func() error {
fmt.Println("game archive")
return nil
}
}


单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package command

import (
"fmt"
"testing"
"time"
)

func TestDemo(t *testing.T) {
// 用于测试,模拟来自客户端的事件
eventChan := make(chan string)
go func() {
events := []string{"start", "archive", "start", "archive", "start", "start"}
for _, e := range events {
eventChan <- e
}
}()
defer close(eventChan)

// 使用命令队列缓存命令
commands := make(chan ICommand, 1000)
defer close(commands)

go func() {
for {
// 从请求或者其他地方获取相关事件参数
event, ok := <-eventChan
if !ok {
return
}

var command ICommand
switch event {
case "start":
command = NewStartCommand()
case "archive":
command = NewArchiveCommand()
}

// 将命令入队
commands <- command
}
}()

for {
select {
case c := <-commands:
c.Execute()
case <-time.After(1 * time.Second):
fmt.Println("timeout 1s")
return
}
}
}


func TestDemoFunc(t *testing.T) {
// 用于测试,模拟来自客户端的事件
eventChan := make(chan string)
go func() {
events := []string{"start", "archive", "start", "archive", "start", "start"}
for _, e := range events {
eventChan <- e
}

}()
defer close(eventChan)

// 使用命令队列缓存命令
commands := make(chan Command, 1000)
defer close(commands)

go func() {
for {
// 从请求或者其他地方获取相关事件参数
event, ok := <-eventChan
if !ok {
return
}

var command Command
switch event {
case "start":
command = StartCommandFunc()
case "archive":
command = ArchiveCommandFunc()
}

// 将命令入队
commands <- command
}
}()

for {
select {
case c := <-commands:
c()
case <-time.After(1 * time.Second):
fmt.Println("timeout 1s")
return
}
}
}