由于最近一直在學習Golang,是以從本節起,所有設計模式學習筆記中的源碼都由Golang來完成~
指令模式:将“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援可撤銷的操作。
仔細看這個定義,我們知道一個指令對象通過在特定接收者(receiver)上綁定一組動作來封裝一個請求。要達到這一點,指令對象将動作和接收者包進對象中。這個對象隻暴露出一個execute()方法,當此方法被調用的時候,接收者就會進行這些動作。從外面看,其他對象不知道究竟哪個接收者進行了哪些動作,隻知道如果調用了execute(),請求的目的就達到了。這些就實作了接收者和調用者的解耦合。
實作指令接口:
首先讓所有的指令對象實作相同的包含一個方法的接口:
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
<code>type command </code><code>interface</code> <code>{</code>
<code> </code><code>execute()</code>
<code>}</code>
<code> </code>
<code>//開燈指令</code>
<code>type lightOnCommand struct {</code>
<code> </code><code>mLight *light </code><code>//指令對象包含的特定接收者</code>
<code> </code>
<code>//傳回一個開燈指令的執行個體對象</code>
<code>func NewLightOnCommand(light *light) command {</code>
<code> </code><code>return</code> <code>&lightOnCommand{mLight: light}</code>
<code>//實作接口方法捆綁接收者的動作</code>
<code>func (</code><code>this</code> <code>*lightOnCommand) execute() {</code>
<code> </code><code>if</code> <code>!</code><code>this</code><code>.mLight.isOn() {</code>
<code> </code><code>this</code><code>.mLight.setOn(</code><code>true</code><code>) </code><code>//開燈</code>
<code> </code><code>}</code>
<code>//關燈指令</code>
<code>type lightOffCommand struct {</code>
<code> </code><code>mLight *light</code>
<code> </code>
<code>func NewLightOffCommand(light *light) command {</code>
<code> </code><code>return</code> <code>&lightOffCommand{mLight: light}</code>
<code>func (</code><code>this</code> <code>*lightOffCommand) execute() {</code>
<code> </code><code>if</code> <code>this</code><code>.mLight.isOn() {</code>
<code> </code><code>this</code><code>.mLight.setOn(</code><code>false</code><code>) </code><code>//關燈</code>
我們應當考慮面向接口程式設計,大部分接收者都有簡單的開關指令,故上述的代碼可改為:
36
<code>type receiver </code><code>interface</code> <code>{</code>
<code> </code><code>setOn(bool) </code><code>//true:開/false:關</code>
<code> </code><code>isOn() bool</code>
<code> </code>
<code>//打開指令 </code>
<code>type onCommand struct {</code>
<code> </code><code>receiver Receiver</code>
<code> </code>
<code>//建立打開指令的執行個體,為該執行個體捆綁接收者 </code>
<code>func NewOnCommand(receiver Receiver) command {</code>
<code> </code><code>return</code> <code>&onCommand{receiver}</code>
<code> </code>
<code>//被封裝的“請求” </code>
<code>func (</code><code>this</code> <code>*onCommand) execute() {</code>
<code> </code><code>if</code> <code>!</code><code>this</code><code>.receiver.isOn() {</code>
<code> </code><code>this</code><code>.receiver.setOn(</code><code>true</code><code>) </code><code>//打開</code>
<code> </code>
<code>//關閉指令 </code>
<code>type offCommand struct {</code>
<code> </code>
<code>func NewOffCommand(receiver Receiver) command {</code>
<code> </code><code>return</code> <code>&offCommand{receiver}</code>
<code>func (</code><code>this</code> <code>*offCommand) execute() {</code>
<code> </code><code>this</code><code>.receiver.setOn(</code><code>false</code><code>) </code><code>//關閉</code>
最後,再來看看用戶端的代碼:
<code>type RemoteController struct {</code>
<code> </code><code>slot command</code>
<code> </code>
<code>func (</code><code>this</code> <code>*RemoteController) SetCommand(command command) {</code>
<code> </code><code>this</code><code>.slot = command</code>
<code>func (</code><code>this</code> <code>*RemoteController) ButtonPressed() {</code>
<code> </code><code>if</code> <code>this</code><code>.slot == nil {</code>
<code> </code><code>panic(</code><code>"Do not assign command to Controller's slot!"</code><code>)</code>
<code> </code><code>this</code><code>.slot.execute()</code>
看看接收者們:
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
<code>const</code> <code>(</code>
<code> </code><code>LIGHT = </code><code>" light"</code>
<code> </code><code>DOOR = </code><code>" door"</code>
<code>)</code>
<code> </code>
<code>//接收者接口 </code>
<code>type Receiver </code><code>interface</code> <code>{</code>
<code> </code><code>setOn(bool)</code>
<code> </code>
<code>type light struct {</code>
<code> </code><code>name string</code>
<code> </code><code>on bool</code>
<code>func (</code><code>this</code> <code>*light) setOn(b bool) {</code>
<code> </code><code>if</code> <code>b {</code>
<code> </code><code>fmt.Println(</code><code>this</code><code>.name + LIGHT + </code><code>" is on."</code><code>)</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>fmt.Println(</code><code>this</code><code>.name + LIGHT + </code><code>" is off."</code><code>)</code>
<code> </code><code>this</code><code>.on = b</code>
<code>func (</code><code>this</code> <code>*light) isOn() bool {</code>
<code> </code><code>return</code> <code>this</code><code>.on</code>
<code>func NewRoomLight() Receiver {</code>
<code> </code><code>return</code> <code>&light{</code><code>"Room"</code><code>, </code><code>false</code><code>}</code>
<code>func NewTableLampLight() Receiver {</code>
<code> </code><code>return</code> <code>&light{</code><code>"Table Lamp"</code><code>, </code><code>false</code><code>}</code>
<code>type door struct {</code>
<code>func (</code><code>this</code> <code>*door) setOn(b bool) {</code>
<code> </code><code>fmt.Println(</code><code>this</code><code>.name + DOOR + </code><code>" is opened."</code><code>)</code>
<code> </code><code>fmt.Println(</code><code>this</code><code>.name + DOOR + </code><code>" is closed."</code><code>)</code>
<code>func (</code><code>this</code> <code>*door) isOn() bool {</code>
<code>func NewGarageDoor() Receiver {</code>
<code> </code><code>return</code> <code>&door{</code><code>"Garage"</code><code>, </code><code>false</code><code>}</code>
<code>func NewKitchenDoor() Receiver {</code>
<code> </code><code>return</code> <code>&door{</code><code>"Kitchen"</code><code>, </code><code>false</code><code>}</code>
來測試下吧~:
<code>func main() {</code>
<code> </code><code>ctrl := </code><code>new</code><code>(command.RemoteController)</code>
<code> </code><code>var roomLight, garageDoor command.Receiver</code>
<code> </code>
<code> </code><code>roomLight = command.NewRoomLight()</code>
<code> </code><code>garageDoor = command.NewGarageDoor()</code>
<code> </code><code>cmdOn := command.NewOnCommand(roomLight)</code>
<code> </code><code>cmdOff := command.NewOffCommand(garageDoor)</code>
<code> </code><code>ctrl.SetCommand(cmdOn)</code>
<code> </code><code>ctrl.ButtonPressed()</code>
<code> </code><code>ctrl.SetCommand(cmdOff)</code>
<a href="http://s3.51cto.com/wyfs02/M00/12/00/wKioL1LxtPqQtdEsAABXMRft1Bk710.jpg" target="_blank"></a>
本文轉自 ponpon_ 51CTO部落格,原文連結:http://blog.51cto.com/liuxp0827/1356520,如需轉載請自行聯系原作者