天天看點

Golang 設計模式 學習筆記(六)指令模式

由于最近一直在學習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>&amp;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>&amp;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>&amp;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>&amp;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>&amp;light{</code><code>"Room"</code><code>, </code><code>false</code><code>}</code>

<code>func NewTableLampLight() Receiver {</code>

<code>    </code><code>return</code> <code>&amp;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>&amp;door{</code><code>"Garage"</code><code>, </code><code>false</code><code>}</code>

<code>func NewKitchenDoor() Receiver {</code>

<code>    </code><code>return</code> <code>&amp;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,如需轉載請自行聯系原作者