由于最近一直在学习Golang,所以从本节起,所有设计模式学习笔记中的源码都由Golang来完成~
命令模式:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
仔细看这个定义,我们知道一个命令对象通过在特定接收者(receiver)上绑定一组动作来封装一个请求。要达到这一点,命令对象将动作和接收者包进对象中。这个对象只暴露出一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。从外面看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道如果调用了execute(),请求的目的就达到了。这些就实现了接收者和调用者的解耦合。
实现命令接口:
首先让所有的命令对象实现相同的包含一个方法的接口:
- type command interface {
- execute()
- }
- //开灯命令
- type lightOnCommand struct {
- mLight *light //命令对象包含的特定接收者
- }
- //返回一个开灯命令的实例对象
- func NewLightOnCommand(light *light) command {
- return &lightOnCommand{mLight: light}
- }
- //实现接口方法捆绑接收者的动作
- func (this *lightOnCommand) execute() {
- if !this.mLight.isOn() {
- this.mLight.setOn(true) //开灯
- }
- }
- //关灯命令
- type lightOffCommand struct {
- mLight *light
- }
- func NewLightOffCommand(light *light) command {
- return &lightOffCommand{mLight: light}
- }
- func (this *lightOffCommand) execute() {
- if this.mLight.isOn() {
- this.mLight.setOn(false) //关灯
- }
- }
我们应当考虑面向接口编程,大部分接收者都有简单的开关命令,故上述的代码可改为:
- type receiver interface {
- setOn(bool) //true:开/false:关
- isOn() bool
- }
- //打开命令
- type onCommand struct {
- receiver Receiver
- }
- //创建打开命令的实例,为该实例捆绑接收者
- func NewOnCommand(receiver Receiver) command {
- return &onCommand{receiver}
- }
- //被封装的“请求”
- func (this *onCommand) execute() {
- if !this.receiver.isOn() {
- this.receiver.setOn(true) //打开
- }
- }
- //关闭命令
- type offCommand struct {
- receiver Receiver
- }
- func NewOffCommand(receiver Receiver) command {
- return &offCommand{receiver}
- }
- func (this *offCommand) execute() {
- if !this.receiver.isOn() {
- this.receiver.setOn(false) //关闭
- }
- }
最后,再来看看客户端的代码:
- type RemoteController struct {
- slot command
- }
- func (this *RemoteController) SetCommand(command command) {
- this.slot = command
- }
- func (this *RemoteController) ButtonPressed() {
- if this.slot == nil {
- panic("Do not assign command to Controller's slot!")
- }
- this.slot.execute()
- }
看看接收者们:
- const (
- LIGHT = " light"
- DOOR = " door"
- )
- //接收者接口
- type Receiver interface {
- setOn(bool)
- isOn() bool
- }
- type light struct {
- name string
- on bool
- }
- func (this *light) setOn(b bool) {
- if b {
- fmt.Println(this.name + LIGHT + " is on.")
- } else {
- fmt.Println(this.name + LIGHT + " is off.")
- }
- this.on = b
- }
- func (this *light) isOn() bool {
- return this.on
- }
- func NewRoomLight() Receiver {
- return &light{"Room",false}
- }
- func NewTableLampLight() Receiver {
- return &light{"Table Lamp",false}
- }
- type door struct {
- name string
- on bool
- }
- func (this *door) setOn(b bool) {
- if b {
- fmt.Println(this.name + DOOR + " is opened.")
- } else {
- fmt.Println(this.name + DOOR + " is closed.")
- }
- this.on = b
- }
- func (this *door) isOn() bool {
- return this.on
- }
- func NewGarageDoor() Receiver {
- return &door{"Garage",false}
- }
- func NewKitchenDoor() Receiver {
- return &door{"Kitchen",false}
- }
来测试下吧~:
- func main() {
- ctrl := new(command.RemoteController)
- var roomLight,garageDoor command.Receiver
- roomLight = command.NewRoomLight()
- garageDoor = command.NewGarageDoor()
- cmdOn := command.NewOnCommand(roomLight)
- cmdOff := command.NewOffCommand(garageDoor)
- ctrl.SetCommand(cmdOn)
- ctrl.ButtonPressed()
- ctrl.SetCommand(cmdOff)
- ctrl.ButtonPressed()
- }