一、概述
? 顧名思義,命令模式其實(shí)和現(xiàn)實(shí)生活中直接下命令的動(dòng)作類(lèi)似,怎么理解這個(gè)命令是理解命令模式的關(guān)鍵?。?!直接說(shuō)結(jié)論是很不負(fù)責(zé)的行為,因此我將會(huì)結(jié)合之后的例子來(lái)向你介紹它,來(lái)幫助你更好的理解,而不是僅僅死記硬背它。這樣你會(huì)在以后需要的時(shí)候想起它并且通過(guò)這個(gè)命令模式幫助你解決問(wèn)題。
二、經(jīng)典舉例
-
遙控器
? 現(xiàn)在你手里有一個(gè)遙控器,上面有很多的按鈕,可以對(duì)應(yīng)到生活中很對(duì)例子,如:電視遙控器、空調(diào)遙控器等等,使用起來(lái)非常的簡(jiǎn)單,我們只需要按下對(duì)應(yīng)功能的按鈕就可以,不需要知道怎么做的,比如說(shuō)開(kāi)關(guān)空調(diào),調(diào)整溫度等等。在這個(gè)場(chǎng)景中,按下按鈕其實(shí)就會(huì)給設(shè)備發(fā)送一個(gè)命令,請(qǐng)先記住這個(gè)場(chǎng)景下的命令,后面會(huì)用到??!
-
點(diǎn)餐
? 你到餐廳點(diǎn)餐,服務(wù)員會(huì)將菜單遞給你,然后你會(huì)挑選菜單上的菜,然后服務(wù)就會(huì)記下來(lái)交給廚師,廚師收到后就會(huì)開(kāi)始準(zhǔn)備這些菜。在這個(gè)過(guò)程中,也是存在命令的,可選擇的命令來(lái)自于菜單,然后你下達(dá)的命令會(huì)由服務(wù)員記錄在小本本上然后傳達(dá)給做菜的廚師。
-
小結(jié)
? 說(shuō)完上面兩個(gè)場(chǎng)景,現(xiàn)在我們來(lái)總結(jié)一下,這兩個(gè)場(chǎng)景中的命令有什么共性。在你繼續(xù)往下查看結(jié)果之前,我建議你先自己思考一下,然后再去下面的結(jié)果。
? 有一天,你突然心血來(lái)潮想通過(guò)遙控器控制空調(diào)放音樂(lè),這可能就沒(méi)辦法做到了,為什么呢?因?yàn)槟闶种械倪b控器上就沒(méi)有這個(gè)命令呀。同樣的道理,你有一天去平日里最?lèi)?ài)的餐廳里想點(diǎn)一道滿(mǎn)漢全席,服務(wù)員看了直搖頭,他不知所措了,為啥呢,因?yàn)椴藛紊蠜](méi)有這道菜。
? 通過(guò)上面的假設(shè),我想你應(yīng)該知道了這個(gè)命令的特點(diǎn)了:
這些 “命令” 都是提前預(yù)設(shè)好的,因此數(shù)量也是有限的,且無(wú)法做到每個(gè)命令都很靈活
命令其實(shí)就是這樣也應(yīng)該這樣,它不是一個(gè)模糊的東西,它的含義非常明確且簡(jiǎn)單。
當(dāng)然,你如果有其他的理解,也希望你能夠在評(píng)論區(qū)不吝分享。
三、代碼示例(Go)
? 示例代碼主要是圍繞命令所做的抽象,命令的方法應(yīng)該盡可能的減少入?yún)⒒蛘邲](méi)有入?yún)?。下面我們就遙控器的場(chǎng)景來(lái)書(shū)寫(xiě)示例代碼:
package main
import "fmt"
// Command 命令對(duì)像
type Command interface {
Execute()
}
// TurnOnLightCommand 開(kāi)燈命令
type TurnOnLightCommand struct {
Light *Light
}
// Execute 執(zhí)行命令
func (c TurnOnLightCommand) Execute() {
c.Light.On()
}
// TurnOffLightCommand 關(guān)燈命令
type TurnOffLightCommand struct {
Light *Light
}
func (c TurnOffLightCommand) Execute() {
c.Light.Off()
}
// TurnOnFanCommand 開(kāi)風(fēng)扇命令
type TurnOnFanCommand struct {
Fan *Fan
}
func (c TurnOnFanCommand) Execute() {
c.Fan.On()
}
// TurnOffFanCommand 關(guān)風(fēng)扇命令
type TurnOffFanCommand struct {
Fan *Fan
}
func (c TurnOffFanCommand) Execute() {
c.Fan.Off()
}
// ConcreteCommand 宏命令,可以執(zhí)行多個(gè)命令
type ConcreteCommand struct {
Commands []Command
}
func (c ConcreteCommand) Execute() {
for _, command := range c.Commands {
command.Execute()
}
}
// Light 燈
type Light struct {
Name string
}
func (l Light) On() {
fmt.Println(l.Name + " on")
}
func (l Light) Off() {
fmt.Println(l.Name + " off")
}
// Fan 風(fēng)扇
type Fan struct {
Name string
}
func (f Fan) On() {
fmt.Println(f.Name + " on")
}
func (f Fan) Off() {
fmt.Println(f.Name + " off")
}
// SimpleRemoteControl 簡(jiǎn)單的遙控器,只有一個(gè)按鈕
type SimpleRemoteControl struct {
Commands Command
}
// ButtonWasPressed 按鈕被按下
func (rc SimpleRemoteControl) ButtonWasPressed() {
rc.Commands.Execute()
}
// NormalRemoteControl 普通的遙控器,有多個(gè)按鈕
type NormalRemoteControl struct {
Commands []Command
}
// ButtonWasPressed 按鈕被按下
func (rc NormalRemoteControl) ButtonWasPressed(index int) {
rc.Commands[index].Execute()
}
func main() {
// 簡(jiǎn)單的遙控器
fmt.Println("簡(jiǎn)單的遙控器")
light := Light{Name: "Living Room"}
remoteControl := SimpleRemoteControl{Commands: TurnOnLightCommand{Light: &light}}
remoteControl.ButtonWasPressed()
// 普通的遙控器
fmt.Println("普通的遙控器")
fan := Fan{Name: "Living Room"}
normalRemoteControl := NormalRemoteControl{Commands: []Command{TurnOnLightCommand{Light: &light}, TurnOffLightCommand{Light: &light}, TurnOnFanCommand{Fan: &fan}, TurnOffFanCommand{Fan: &fan}}}
normalRemoteControl.ButtonWasPressed(0)
normalRemoteControl.ButtonWasPressed(1)
normalRemoteControl.ButtonWasPressed(2)
normalRemoteControl.ButtonWasPressed(3)
// 通過(guò)宏,讓一個(gè)按鈕可以執(zhí)行多個(gè)命令
fmt.Println("通過(guò)宏,讓一個(gè)按鈕可以執(zhí)行多個(gè)命令")
normalRemoteControl.Commands = []Command{ConcreteCommand{Commands: []Command{TurnOnLightCommand{Light: &light}, TurnOnFanCommand{Fan: &fan}}}, ConcreteCommand{Commands: []Command{TurnOffLightCommand{Light: &light}, TurnOffFanCommand{Fan: &fan}}}}
normalRemoteControl.ButtonWasPressed(0)
}
-
分析
? 代碼中最核心的是抽象了
Command
,通過(guò)這個(gè)接口的Execute()
方法不關(guān)心命令究竟是如何執(zhí)行的,畢竟它僅僅只是命令而已。? 有了這個(gè)接口,我們就可以在此基礎(chǔ)之上拓展很多新的應(yīng)用場(chǎng)景出來(lái),就比如示例中的
宏命令
——由幾個(gè)命令組合而成,除此之外,還有可以有很多其他拓展,希望你們能夠自己親自去實(shí)現(xiàn),這樣能夠提升自己的理解。可拓展的應(yīng)用場(chǎng)景:
-
撤銷(xiāo)/回滾功能
這個(gè)很好理解,其實(shí)就是在
Command
接口中增加一個(gè)Undo()
方法,然后再把執(zhí)行過(guò)的命令放入棧中,進(jìn)行命令回滾時(shí),只需要執(zhí)行出棧命令的Undo()
方法即可。 -
遠(yuǎn)程執(zhí)行
既然命令已經(jīng)被抽象成了對(duì)象,那么也就和對(duì)象一樣可以被序列化(變成可傳輸?shù)淖址┤缓髠鬏數(shù)竭h(yuǎn)端去或者持久化到數(shù)據(jù)庫(kù)中。
-
其他
-
四、總結(jié)
? 其實(shí)命令模式并不難,最最最核心的正入它的名字一樣,是對(duì)業(yè)務(wù) “命令” 的抽象,因此也有些地方把這個(gè)設(shè)計(jì)模式成為 調(diào)用封裝
。
? 有了上面的理解后我們來(lái)體會(huì)一下此模式的定義,相信你會(huì)有更深刻的理解:
命令模式將 “請(qǐng)求” 封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或日志來(lái)參數(shù)化其他對(duì)象。命令模式支持可撤銷(xiāo)的操作文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-669810.html
? 以上,便是此文章的全部?jī)?nèi)容了,希望你能有收獲,如果內(nèi)容存在錯(cuò)誤的地方,也歡迎指出文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-669810.html
到了這里,關(guān)于設(shè)計(jì)模式大白話(huà)——命令模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!