iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Software Development

Hey! Go Design Patterns系列 第 28

DAY 28:Command Pattern,將動作已指令一個一個完成

什麼是 Command Pattern?

將建立指令與實際執行分離

問題情境

PS5 有特定操作 CPU 指令的實作.ACommand().BCommand(),如果現在又多了新的特定操作,必須修改PS5{},這不符合開閉原則,我們需要有方法滿足開閉原則。

package main

import "fmt"

type CPU struct{}

func (CPU) ADoSomething() {
	fmt.Println("a do something")
}
func (CPU) BDoSomething() {
	fmt.Println("b do something")
}
func (CPU) CDoSomething() {
	fmt.Println("c do something")
}

type PS5 struct {
	cpu CPU
}

func (p PS5) ACommand() {
	p.cpu.ADoSomething()
	p.cpu.CDoSomething()
}
func (p PS5) BCommand() {
	p.cpu.ADoSomething()
	p.cpu.BDoSomething()
}
func main() {
	cpu := CPU{}
	ps5 := PS5{cpu}
	ps5.ACommand()
	ps5.BCommand()
}

解決方式

新增Commandinterface,裡頭有Execute()這個 function,並實作ACommand{}BCommand{}讓指令的建立從PS5{}中分離出來,即滿足開閉原則。

最後透過PS5{}.SetCommand()來將符合Commandinterface 的指令設定給 PS5,再透過PS5{}.DoCommand()選擇要執行的指令。

package main

import "fmt"

type CPU struct{}

func (CPU) ADoSomething() {
	fmt.Println("a do something")
}
func (CPU) BDoSomething() {
	fmt.Println("b do something")
}
func (CPU) CDoSomething() {
	fmt.Println("c do something")
}

type Command interface {
	Execute()
}

type ACommand struct {
	cpu CPU
}

func (a ACommand) Execute() {
	a.cpu.ADoSomething()
	a.cpu.CDoSomething()
}

type BCommand struct {
	cpu CPU
}

func (b BCommand) Execute() {
	b.cpu.ADoSomething()
	b.cpu.BDoSomething()
}

type PS5 struct {
	commands map[string]Command
}

func (p *PS5) SetCommand(name string, command Command) {
	p.commands[name] = command
}

func (p *PS5) DoCommand(name string) {
	p.commands[name].Execute()
}

func main() {
	cpu := CPU{}
	aCommand := ACommand{cpu}
	bCommand := BCommand{cpu}
	ps5 := PS5{make(map[string]Command)}
	ps5.SetCommand("a", aCommand)
	ps5.SetCommand("b", bCommand)
	ps5.DoCommand("a")
	ps5.DoCommand("b")
}

上一篇
DAY 27:Chain of Responsibility,將實作透過串串樂串起來
下一篇
DAY 29:Iterator Pattern,迭代各種不同的物件
系列文
Hey! Go Design Patterns30

尚未有邦友留言

立即登入留言