掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流
大家好,這里是每周都陪你進(jìn)步的網(wǎng)管,假期歸來(lái)咱們繼續(xù)更新設(shè)計(jì)模式系列,這次要和大家一起學(xué)習(xí)的是命令模式,如果你對(duì)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)感興趣,這個(gè)模式一定要好好學(xué),命令模式是DDD風(fēng)格的框架中高頻使用的一個(gè)模式。

創(chuàng)新互聯(lián)是一家專(zhuān)注于成都做網(wǎng)站、網(wǎng)站建設(shè)與策劃設(shè)計(jì),三山網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:三山等地區(qū)。三山做網(wǎng)站價(jià)格咨詢(xún):18980820575
命令模式是一種行為型模式。它通過(guò)將請(qǐng)求封裝為一個(gè)獨(dú)立的對(duì)象即命令對(duì)象,來(lái)解耦命令的調(diào)用者和接收者,使得調(diào)用者和接收者不直接交互。在命令對(duì)象里會(huì)包含請(qǐng)求相關(guān)的全部信息,每一個(gè)命令都是一個(gè)操作的請(qǐng)求: 請(qǐng)求方發(fā)出請(qǐng)求要求執(zhí)行一個(gè)操作; 接收方收到請(qǐng)求,并執(zhí)行操作。
命令模式中有如下必須存在的基礎(chǔ)組件:
直接這么描述聽(tīng)起來(lái)比較抽象,下面我們結(jié)合UML類(lèi)圖詳細(xì)看一下命令模式內(nèi)部這幾種基礎(chǔ)組件的特性和具有的行為。
命令模式的構(gòu)成如下圖所示
請(qǐng)求的接收者Receiver我們做了簡(jiǎn)化,根據(jù)實(shí)際場(chǎng)景復(fù)雜度的需要我們也可以進(jìn)一步抽象出接口和實(shí)現(xiàn)類(lèi),圖中表示的命令模式一共由五種角色構(gòu)成,下面詳細(xì)解釋下它們各自的特性和具有的行為
發(fā)送者是通常我們能接觸到的終端,比如電視的遙控器,點(diǎn)擊音量按鈕發(fā)送加音量的命令,電視機(jī)里的芯片就是接收者負(fù)責(zé)完成音量添加的處理邏輯。
下面我們通過(guò)一個(gè)讓PS5完成各種操作的例子,結(jié)合Golang代碼實(shí)現(xiàn)理解一下用代碼怎么實(shí)現(xiàn)命令模式。
假設(shè)PS5的CPU支持A、B、C三個(gè)命令操作,
"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
type CPU struct{}
func (CPU) ADoSomething() {
fmt.Println("a do something")
}
func (CPU) BDoSomething() {
fmt.Println("b do something")
}
type PS5 struct {
cpu CPU
}
func (p PS5) ACommand() {
p.cpu.ADoSomething()
}
func (p PS5) BCommand() {
p.cpu.ADoSomething()
}
func main() {
cpu := CPU{}
ps5 := PS5{cpu}
ps5.ACommand()
ps5.BCommand()
}后續(xù)還可能會(huì)給CPU增加其他命令操作,以及需要支持命令宏(即命令組合操作)。如果每次都修改PS5的類(lèi)定義,顯然不符合面向?qū)ο箝_(kāi)閉原則(Open close principle)的設(shè)計(jì)理念。
通過(guò)命令模式,我們把PS5抽象成命令發(fā)送者、CPU對(duì)象作為執(zhí)行業(yè)務(wù)邏輯的命令接收者,然后引入引入Command 接口把兩者做解耦,來(lái)滿(mǎn)足開(kāi)閉原則。
下面看一下用命令模式解耦后的代碼實(shí)現(xiàn),模式中各個(gè)角色的職責(zé)、實(shí)現(xiàn)思路等都在代碼注釋里做了標(biāo)注,咱們直接看代碼吧。
"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
// 命令接收者,負(fù)責(zé)邏輯的執(zhí)行
type CPU struct{}
func (CPU) ADoSomething(param int) {
fmt.Printf("a do something with param %v\n", param)
}
func (CPU) BDoSomething(param1 string, param2 int) {
fmt.Printf("b do something with params %v and %v \n", param1, param2)
}
func (CPU) CDoSomething() {
fmt.Println("c do something with no params")
}
// 接口中僅聲明一個(gè)執(zhí)行命令的方法 Execute()
type Command interface {
Execute()
}
// 命令對(duì)象持有一個(gè)指向接收者的引用,以及請(qǐng)求中的所有參數(shù),
type ACommand struct {
cpu *CPU
param int
}
// 命令不會(huì)進(jìn)行邏輯處理,調(diào)用Execute方法會(huì)將發(fā)送者的請(qǐng)求委派給接收者對(duì)象。
func (a ACommand) Execute() {
a.cpu.ADoSomething(a.param)
a.cpu.CDoSomething()// 可以執(zhí)行多個(gè)接收者的操作完成命令宏
}
func NewACommand(cpu *CPU, param int) Command {
return ACommand{cpu, param}
}
"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
type BCommand struct {
state bool // Command 里可以添加些狀態(tài)用作邏輯判斷
cpu *CPU
param1 string
param2 int
}
func (b BCommand) Execute() {
if b.state {
return
}
b.cpu.BDoSomething(b.param1, b.param2)
b.state = true
b.cpu.CDoSomething()
}
func NewBCommand(cpu *CPU, param1 string, param2 int) Command {
return BCommand{false,cpu, param1, param2}
}
type PS5 struct {
commands map[string]Command
}
// SetCommand方法來(lái)將 Command 指令設(shè)定給PS5。
func (p *PS5) SetCommand(name string, command Command) {
p.commands[name] = command
}
// DoCommand方法選擇要執(zhí)行的命令
func (p *PS5) DoCommand(name string) {
p.commands[name].Execute()
}
func main() {
cpu := CPU{}
// main方法充當(dāng)客戶(hù)端,創(chuàng)建并配置具體命令對(duì)象, 完成命令與執(zhí)行操作的接收者的關(guān)聯(lián)。
ps5 := PS5{make(map[string]Command)}
ps5.SetCommand("a", NewACommand(&cpu, 1))
ps5.SetCommand("b", NewBCommand(&cpu, "hello", 2))
ps5.DoCommand("a")
ps5.DoCommand("b")
}
本文的完整源碼,已經(jīng)同步收錄到我整理的電子教程里啦,可向我的公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送關(guān)鍵字【設(shè)計(jì)模式】領(lǐng)取。
公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送關(guān)鍵字【設(shè)計(jì)模式】領(lǐng)取。
關(guān)于命令模式的學(xué)習(xí)和實(shí)踐應(yīng)用,推薦有Java背景的同學(xué)看一下阿里開(kāi)源的框架COLA 3.0,里面融合了不少DDD的概念,其中的Application層主要就是各種Command、Query對(duì)象封裝了客戶(hù)端的請(qǐng)求,它們的Execute方法負(fù)責(zé)將請(qǐng)求轉(zhuǎn)發(fā)給Domain層進(jìn)行處理從而完成業(yè)務(wù)邏輯。
最后我們?cè)賮?lái)總結(jié)一下命令模式的優(yōu)缺點(diǎn)。
命令模式的優(yōu)點(diǎn)
命令模式的缺點(diǎn)

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流