diff --git a/structure/22_bridge/README.md b/structure/22_bridge/README.md index 4073f65..edc6130 100644 --- a/structure/22_bridge/README.md +++ b/structure/22_bridge/README.md @@ -1,8 +1,21 @@ # 桥接模式 -桥接模式分离抽象部分和实现部分。使得两部分独立扩展。 +桥接模式类似于策略模式,原因在于他们都将行为交给了另一个接口实现,再组合实现完整功能/流程/业务. -桥接模式类似于策略模式,原因在于他们都将行为交给了另一个接口实现,再组合实现 -区别在于策略模式封装一系列算法使得算法可以互相替换,关键点在于可以动态替换,但是桥接模式的特点是,一旦组合运行时一般不会发生变化. +区别在于策略模式封装一系列算法/方法/功能/使得他们可以互相替换,关键点在于策略模式的实现方法可以动态替换,但是桥接模式的特点是,一旦组合运行时一般不会发生变化. +桥接模式的变化点在于调用方是变化的. +在策略模式的例子中,银行就一个,但是储户类型是多个,银行需要为不同类型的用户服务,银行有同一个规则流程和处理方法,但是不同的用户对相同处理过程的响应和处理不一样。 + +在桥接模式中,消息类型是多个,转给不同的处理对象. + +演示1个例子,场景如下: + +对于Web应用系统,当平台后端收到消息并需要推送的时候,常见有四种选择: +1、通过第三方的的Internet通道,离线推送到手机,通知用户 +2、通过邮件通知到用户 +3、通过在线的长连接进行websocket推送 +4、通过手机4G/5G的短信通道通知到用户 + +选择其中的二三两类进行演示 diff --git a/structure/22_bridge/bridge.go b/structure/22_bridge/bridge.go index edff839..4aa7db8 100644 --- a/structure/22_bridge/bridge.go +++ b/structure/22_bridge/bridge.go @@ -2,58 +2,78 @@ package bridge import "fmt" -type AbstractMessage interface { - SendMessage(text, to string) +//IMessage 发送消息接口 +type IMessage interface { + NoticeUser(text string) + Priority() int } -type MessageImplementer interface { - Send(text, to string) +//ISMSMessage send SMS MSG +type ISMSMessage interface { + //延迟接口的实现到其他类中 + NoticeUser(text string, noticeMessage IMessage) } -type MessageSMS struct{} - -func ViaSMS() MessageImplementer { - return &MessageSMS{} +//WSMessage MSG +type WSMessage struct { + Handler ISMSMessage //持有进一步实现的引用关系 + Level int } -func (*MessageSMS) Send(text, to string) { - fmt.Printf("send %s to %s via SMS", text, to) -} - -type MessageEmail struct{} - -func ViaEmail() MessageImplementer { - return &MessageEmail{} -} - -func (*MessageEmail) Send(text, to string) { - fmt.Printf("send %s to %s via Email", text, to) -} - -type CommonMessage struct { - method MessageImplementer -} - -func NewCommonMessage(method MessageImplementer) *CommonMessage { - return &CommonMessage{ - method: method, +//NoticeUser by SMS +func (w *WSMessage) NoticeUser(text string) { + //转递消息给其他对象,相当于承上启下 + fmt.Println("Websocket Notice User...", text) + //转递消息给其他对象,相当于承上启下,并且需要把上下文变量传递下去 + if w.Handler != nil { + w.Handler.NoticeUser(text, w) } + } -func (m *CommonMessage) SendMessage(text, to string) { - m.method.Send(text, to) +//Priority of SMS +func (w *WSMessage) Priority() int { + return w.Level } -type UrgencyMessage struct { - method MessageImplementer +//EmailMessage MSG +type EmailMessage struct { + Handler ISMSMessage + Level int } -func NewUrgencyMessage(method MessageImplementer) *UrgencyMessage { - return &UrgencyMessage{ - method: method, +//NoticeUser by SMS +func (e *EmailMessage) NoticeUser(text string) { + //转递消息给其他对象,相当于承上启下,并且需要把上下文变量传递下去 + fmt.Println("Email Notice User...", text) + if e.Handler != nil { + e.Handler.NoticeUser(text, e) } + } -func (m *UrgencyMessage) SendMessage(text, to string) { - m.method.Send(fmt.Sprintf("[Urgency] %s", text), to) +//Priority of SMS +func (e *EmailMessage) Priority() int { + return e.Level +} + +///需要实现具体的消息发送行为 + +//EmergencyWSMessage 紧急的短信消息 +type EmergencyWSMessage struct { +} + +//NoticeUser by email +func (e *EmergencyWSMessage) NoticeUser(text string, noticeMessage IMessage) { + fmt.Println("Notice User", text, " By Websocket:", "with Level: ", noticeMessage.Priority()) +} + +//EmergencyEmailMessage 紧急的短信消息 +type EmergencyEmailMessage struct { +} + +//NoticeUser by email +func (e *EmergencyEmailMessage) NoticeUser(text string, noticeMessage IMessage) { + fmt.Println("Notice User:", text, " By Email:", "with Level: ", noticeMessage.Priority()) + } diff --git a/structure/22_bridge/bridge_test.go b/structure/22_bridge/bridge_test.go index 23e155d..dd5717b 100644 --- a/structure/22_bridge/bridge_test.go +++ b/structure/22_bridge/bridge_test.go @@ -1,29 +1,27 @@ package bridge -func ExampleCommonSMS() { - m := NewCommonMessage(ViaSMS()) - m.SendMessage("have a drink?", "bob") - // Output: - // send have a drink? to bob via SMS -} +import "testing" -func ExampleCommonEmail() { - m := NewCommonMessage(ViaEmail()) - m.SendMessage("have a drink?", "bob") - // Output: - // send have a drink? to bob via Email -} +func TestSendMessage(t *testing.T) { -func ExampleUrgencySMS() { - m := NewUrgencyMessage(ViaSMS()) - m.SendMessage("have a drink?", "bob") - // Output: - // send [Urgency] have a drink? to bob via SMS -} + //注意看这里,接口的实例关系在初始化时候是固定的 + ws := &WSMessage{&EmergencyWSMessage{}, 100} -func ExampleUrgencyEmail() { - m := NewUrgencyMessage(ViaEmail()) - m.SendMessage("have a drink?", "bob") - // Output: - // send [Urgency] have a drink? to bob via Email + //注意看这里,接口的实例关系在初始化时候是固定的 + email := &EmailMessage{&EmergencyEmailMessage{}, 10} + + ws.NoticeUser("Miss White ,Let's Drink") + email.NoticeUser("Miss White,Fire!,Fire!") + + ews := &EmergencyWSMessage{} + eem := &EmergencyEmailMessage{} + list := []IMessage{ + &WSMessage{ews, 50}, + &WSMessage{ews, 100}, + &EmailMessage{eem, 10}, + &EmailMessage{eem, 20}, + } + for _, v := range list { + v.NoticeUser("Let’s go for fun") + } }