最近複習設計模式
拜讀譚勇德的<<設計模式就該這樣學>>
本系列筆記擬採用golang練習之golang
中介者模式(Mediator Pattern)又叫做調解者模式或調停者模式。 用一箇中介對象封裝一系列對象交互, 中介者使各對象不須要顯式地相互做用, 從而使其耦合鬆散, 並且能夠獨立地改變它們之間的交互, 屬於行爲型設計模式。 中介者模式主要適用於如下應用場景。 (1)系統中對象之間存在複雜的引用關係,產生的相互依賴關係結構混亂且難以理解。 (2)交互的公共行爲,若是須要改變行爲,則能夠增長新的中介者類。 (摘自 譚勇德 <<設計模式就該這樣學>>)
mediator_pattern_test.go設計模式
package behavioral_patterns import ( "learning/gooop/behavioral_patterns/mediator" "testing" ) func Test_MediatorPattern(t *testing.T) { // 設備註冊 center := mediator.DefaultCloudCenter light := mediator.NewMockSmartLight(1) center.Register(light) fnCallAndLog := func(fn func() error) { e := fn() if e != nil { t.Log(e) } } // 建立app app := mediator.NewMockPhoneApp(mediator.DefaultCloudMediator) // 設備控制測試 fnCallAndLog(func() error { return app.LightOpen(1) }) fnCallAndLog(func() error { return app.LightSwitchMode(1, 1) }) fnCallAndLog(func() error { return app.LightSwitchMode(1, 2) }) fnCallAndLog(func() error { return app.LightClose(1) }) }
t$ go test -v mediator_pattern_test.go === RUN Test_MediatorPattern tMockSmartLight.open, id=1 tMockSmartLight.switchMode, id=1, mode=1 tMockSmartLight.switchMode, id=1, mode=2 tMockSmartLight.close, id=1 --- PASS: Test_MediatorPattern (0.00s) PASS ok command-line-arguments 0.002s
虛擬的手機app, 用於跟雲中心通訊, 控制智能設備架構
package mediator import ( "errors" "fmt" ) type MockPhoneApp struct { mediator ICloudMediator } func NewMockPhoneApp(mediator ICloudMediator) *MockPhoneApp { return &MockPhoneApp{ mediator, } } func (me *MockPhoneApp) LightOpen(id int) error { return me.lightCommand(id, "light open") } func (me *MockPhoneApp) LightClose(id int) error { return me.lightCommand(id, "light close") } func (me *MockPhoneApp) LightSwitchMode(id int, mode int) error { return me.lightCommand(id, fmt.Sprintf("light switch_mode %v", mode)) } func (me *MockPhoneApp) lightCommand(id int, cmd string) error { res := me.mediator.Command(id, cmd) if res != "OK" { return errors.New(res) } return nil }
雲中心面向手機app的接口app
package mediator type ICloudMediator interface { Command(id int, cmd string) string }
雲中心面向智能設備的註冊接口運維
package mediator type ICloudCenter interface { Register(dev ISmartDevice) }
智能設備接口oop
package mediator type ISmartDevice interface { ID() int Command(cmd string) string }
虛擬的雲中心服務類, 面向手機app實現ICloudMediator接口, 面向智能設備實現ICloudCenter接口單元測試
package mediator import "sync" type tMockCloudMediator struct { mDevices map[int]ISmartDevice mRWMutex *sync.RWMutex } func newMockCloudMediator() ICloudMediator { return &tMockCloudMediator{ make(map[int]ISmartDevice), new(sync.RWMutex), } } func (me *tMockCloudMediator) Register(it ISmartDevice) { me.mRWMutex.Lock() defer me.mRWMutex.Unlock() me.mDevices[it.ID()] = it } func (me *tMockCloudMediator) Command(id int, cmd string) string { me.mRWMutex.RLock() defer me.mRWMutex.RUnlock() it,ok := me.mDevices[id] if !ok { return "device not found" } return it.Command(cmd) } var DefaultCloudMediator = newMockCloudMediator() var DefaultCloudCenter = DefaultCloudMediator.(ICloudCenter)
虛擬的智能燈設備, 實現ISmartDevice接口測試
package mediator import ( "fmt" "strconv" "strings" ) type tMockSmartLight struct { id int } func NewMockSmartLight(id int) ISmartDevice { return &tMockSmartLight{ id, } } func (me *tMockSmartLight) ID() int { return me.id } func (me *tMockSmartLight) Command(cmd string) string { if cmd == "light open" { e := me.open() if e != nil { return e.Error() } } else if cmd == "light close" { e := me.close() if e != nil { return e.Error() } } else if strings.HasPrefix(cmd, "light switch_mode") { args := strings.Split(cmd, " ") if len(args) != 3 { return "invalid switch command" } n, e := strconv.Atoi(args[2]) if e != nil { return "invalid mode number" } e = me.switchMode(n) if e != nil { return e.Error() } } else { return "unrecognized command" } return "OK" } func (me *tMockSmartLight) open() error { fmt.Printf("tMockSmartLight.open, id=%v\n", me.id) return nil } func (me *tMockSmartLight) close() error { fmt.Printf("tMockSmartLight.close, id=%v\n", me.id) return nil } func (me *tMockSmartLight) switchMode(mode int) error { fmt.Printf("tMockSmartLight.switchMode, id=%v, mode=%v\n", me.id, mode) return nil }
中介者模式的優勢 (1)減小類間依賴,將多對多依賴轉化成一對多,下降了類間耦合。 (2)類間各司其職,符合迪米特法則。 中介者模式的缺點 中介者模式將本來多個對象直接的相互依賴變成了中介者和多個同事類的依賴關係。 當同事類越多時,中介者就會越臃腫,變得複雜且難以維護。 (摘自 譚勇德 <<設計模式就該這樣學>>)
(end)設計