目录
[桥接模式(Bridge Pattern)](#桥接模式(Bridge Pattern))
桥接模式(Bridge Pattern)
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类,这两种类型的类可被结构化改变而互不影响。桥接模式的目的是将抽象与实现分离,使它们可以独立地变化,该模式通过将一个对象的抽象部分与它的实现部分分离,使它们可以独立地改变。它通过组合的方式,而不是继承的方式,将抽象和实现的部分连接起来。
桥接模式的 核心角色
- 抽象(Abstraction):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个 Implementor(实现类接口)类型的对象并可以维护该对象,它与 Implementor 之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
- 扩展抽象(Refined Abstraction):扩充由 Abstraction 定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在 Abstraction 中声明的抽象业务方法,在 RefinedAbstraction 中可以调用在 Implementor 中定义的业务方法,可以是抽象类的子类或具体实现类。
- 实现(Implementor):定义实现类的接口,这个接口不一定要与 Abstraction 的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor 接口仅提供基本操作,而 Abstraction 定义的接口可能会做更多更复杂的操作。Implementor 接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在 Abstraction 中不仅拥有自己的方法,还可以调用到 Implementor 中定义的方法,使用关联关系来替代继承关系。
- 具体实现(Concrete Implementor):具体实现 Implementor 接口,在不同的 ConcreteImplementor 中提供基本操作的不同实现,在程序运行时,ConcreteImplementor 对象将替换其父类对象,提供给抽象类具体的业务操作方法。
优缺点
(1)优点:
- 抽象和实现的分离。
- 优秀的扩展能力。
- 实现细节对客户透明。
(2)缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
使用场景
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
代码实现
Go
package main
import "fmt"
// 消息发送接口
type MessageSend interface {
send(msg string)
}
// 短信消息
type SMS struct {
}
func (s *SMS) send(msg string) {
fmt.Println("sms 发送的消息内容为: " + msg)
}
// 邮件消息
type Email struct {
}
func (e *Email) send(msg string) {
fmt.Println("email 发送的消息内容为: " + msg)
}
// AppPush消息
type AppPush struct {
}
func (a *AppPush) send(msg string) {
fmt.Println("appPush 发送的消息内容为: " + msg)
}
// 站内信消息
type Letter struct {
}
func (l *Letter) send(msg string) {
fmt.Println("站内信 发送的消息内容为: " + msg)
}
// 用户触达父类,包含触达方式数组messageSends
type Touch struct {
messageSends []MessageSend
}
// 触达方法,调用每一种方式进行触达
func (t *Touch) do(msg string) {
for _, s := range t.messageSends {
s.send(msg)
}
}
// 紧急消息做用户触达
type TouchUrgent struct {
base Touch
}
// 紧急消息,先从db中获取各种信息,然后使用各种触达方式通知用户
func (t *TouchUrgent) do(msg string) {
fmt.Println("touch urgent 从db获取接收人等信息")
t.base.do(msg)
}
// 普通消息做用户触达
type TouchNormal struct {
base Touch
}
// 普通消息,先从文件中获取各种信息,然后使用各种触达方式通知用户
func (t *TouchNormal) do(msg string) {
fmt.Println("touch normal 从文件获取接收人等信息")
t.base.do(msg)
}
func main() {
//触达方式
sms := &SMS{}
appPush := &AppPush{}
letter := &Letter{}
email := &Email{}
//根据触达类型选择触达方式
fmt.Println("-------------------touch urgent")
touchUrgent := TouchUrgent{
base: Touch{
messageSends: []MessageSend{sms, appPush, letter, email},
},
}
touchUrgent.do("urgent情况")
fmt.Println("-------------------touch normal")
touchNormal := TouchNormal{ //
base: Touch{
messageSends: []MessageSend{sms, appPush, letter, email},
},
}
touchNormal.do("normal情况")
}