From fd36971c2124fc29d0a094e52c9966969a2dd07c Mon Sep 17 00:00:00 2001 From: Edward Date: Tue, 5 May 2020 22:03:44 +0800 Subject: [PATCH] finish cmd pattern --- behavior/11_command/README.md | 19 ++--- behavior/11_command/command.go | 117 +++++++++++++++------------- behavior/11_command/command_test.go | 44 +++++++---- 3 files changed, 101 insertions(+), 79 deletions(-) diff --git a/behavior/11_command/README.md b/behavior/11_command/README.md index e54e44b..a48f102 100644 --- a/behavior/11_command/README.md +++ b/behavior/11_command/README.md @@ -1,20 +1,17 @@ # 命令模式 -命令模式本质是把某个对象的方法调用封装到对象中,方便传递、存储、调用。 +命令模式也是一个响应模式,其主要作用是分离命令发出者和命令执行者,两者只要按照命令定义的约束交互,就可以各自变化。 -示例中把主板单中的启动(start)方法和重启(reboot)方法封装为命令对象,再传递到主机(box)对象中。于两个按钮进行绑定: +现实生活中的例子也很多,比如,告知店员买XX奶茶,遥控器控制电视,就是命令模式,以及现在AI能力,大部分情况下,也是基于命令识别进行响应的,还有军训的时候,队列根据教官的各种口令进行变化,更多典型的命令模式。 -* 第一个机箱(box1)设置按钮1(buttion1) 为开机按钮2(buttion2)为重启。 -* 第二个机箱(box1)设置按钮2(buttion2) 为开机按钮1(buttion1)为重启。 - -从而得到配置灵活性。 +命令模式中中的一个特点是每个`命令`都是一个类型(struct)。 -除了配置灵活外,使用命令模式还可以用作: +命令模式的关键角色: -* 批处理 -* 任务队列 -* undo, redo + *接收者(Receiver): 执行请求相关的操作Execute() + *调用者(Invoker): 发出命令的一方 + *命令接口(Command) + *具体命令的结构体(Command) -等把具体命令封装到对象中使用的场合 diff --git a/behavior/11_command/command.go b/behavior/11_command/command.go index 23ca638..9b9082e 100644 --- a/behavior/11_command/command.go +++ b/behavior/11_command/command.go @@ -2,64 +2,75 @@ package command import "fmt" -type Command interface { +//////////////////////////////// +//这里使用军训的例子,使用队列向左转,向右转,向后转的口令 +//命令发出者是教官,命令执行者是队列 + +//ICommand 命令接口,队列要进行响应 +type ICommand interface { Execute() } -type StartCommand struct { - mb *MotherBoard +//Troop 队列 +type Troop struct{ name string } + +//Execute cmd +func (t *Troop) Execute() { + fmt.Println("cmd had been executed by", t.name) } -func NewStartCommand(mb *MotherBoard) *StartCommand { - return &StartCommand{ - mb: mb, +//TurnLeftCommand 向左转 +type TurnLeftCommand struct { + //可以携带参数,每个命令有一个接收者,去执行 + receiver ICommand +} + +//Execute 执行向左转 +func (t *TurnLeftCommand) Execute() { + fmt.Print("Troop Turn Left\n") + t.receiver.Execute() +} + +//TurnRightCommand 向右转 +type TurnRightCommand struct { + //可以携带参数 + receiver ICommand +} + +//Execute 执行向右转 +func (t *TurnRightCommand) Execute() { + fmt.Print("Troop Turn Right\n") + t.receiver.Execute() +} + +//TurnBackCommand 向后转 +type TurnBackCommand struct { + //可以携带参数 + holdTime int //保持时间 + receiver ICommand +} + +//Execute 执行向后转 +func (t *TurnBackCommand) Execute() { + fmt.Print("Troop Turn Back\n") + t.receiver.Execute() +} + +// Instructor 教官 +type Instructor struct { + commands []ICommand +} + +//AddCommand 教官喊口令一般都是一连串 +func (i *Instructor) AddCommand(c ICommand) { + i.commands = append(i.commands, c) +} + +//Execute 教官的Execute是发出命令 +func (i *Instructor) Execute() { + + for _, cmd := range i.commands { + cmd.Execute() } -} -func (c *StartCommand) Execute() { - c.mb.Start() -} - -type RebootCommand struct { - mb *MotherBoard -} - -func NewRebootCommand(mb *MotherBoard) *RebootCommand { - return &RebootCommand{ - mb: mb, - } -} - -func (c *RebootCommand) Execute() { - c.mb.Reboot() -} - -type MotherBoard struct{} - -func (*MotherBoard) Start() { - fmt.Print("system starting\n") -} - -func (*MotherBoard) Reboot() { - fmt.Print("system rebooting\n") -} - -type Box struct { - buttion1 Command - buttion2 Command -} - -func NewBox(buttion1, buttion2 Command) *Box { - return &Box{ - buttion1: buttion1, - buttion2: buttion2, - } -} - -func (b *Box) PressButtion1() { - b.buttion1.Execute() -} - -func (b *Box) PressButtion2() { - b.buttion2.Execute() } diff --git a/behavior/11_command/command_test.go b/behavior/11_command/command_test.go index 6bfb52a..7e080d5 100644 --- a/behavior/11_command/command_test.go +++ b/behavior/11_command/command_test.go @@ -1,20 +1,34 @@ package command -func ExampleCommand() { - mb := &MotherBoard{} - startCommand := NewStartCommand(mb) - rebootCommand := NewRebootCommand(mb) +import "testing" - box1 := NewBox(startCommand, rebootCommand) - box1.PressButtion1() - box1.PressButtion2() +func TestTroopCommand(t *testing.T) { + + //教官 + in := Instructor{} + + //受训队伍1 + tr1 := &Troop{name: "girl team"} + turnLeft := &TurnLeftCommand{receiver: tr1} + + //受训队伍2 + tr2 := &Troop{name: "boy team"} + + turnRight := &TurnLeftCommand{receiver: tr2} + + //准备命令发给不同的队伍 + in.AddCommand(turnRight) + in.AddCommand(turnLeft) + + turnback := &TurnBackCommand{receiver: tr2} + + in.AddCommand(turnback) + + turnback = &TurnBackCommand{receiver: tr1} + + in.AddCommand(turnback) + + //开始发布指令 + in.Execute() - box2 := NewBox(rebootCommand, startCommand) - box2.PressButtion1() - box2.PressButtion2() - // Output: - // system starting - // system rebooting - // system rebooting - // system starting }