桥接模式
前言
桥接模式的代码实现非常简单,但是理解起来稍微有点难度,并且应用场景也比较局限,所以,相当于代理模式来说,桥接模式在实际的项目中并没有那么常用,所以能分辨出来就行了,这里不做重点的学习。
定义
桥接模式:将抽象部分和它的实现部分分离,使他们都可以独立的变化。
看完定义还是一脸懵
举个栗子吧:使用大话模式中的手机栗子来分析
我们知道不同品牌的手机以及不同品牌手机的不同版本对于手机软件的要求是不一样的,可能在M品牌中的软件,就不能在N品牌的手机中使用。M品牌中10代版本的软件可能就不能在1代版本中安装使用。
我们如果使用代码去实现这种关系:
1、按照品牌分类实现的结构图
2、按照软件分类实现的结构图
上面的第一种和第二种实现方式
如果对于手机品牌我们需要增加A,B,C三种,对于软件,我们增加笔记,输入法,闹钟。。。
那么原来已经写好的模块也需要修改,显然这种修改是灾难级别的,新功能的添加就需要很多模块被修改
3、使用桥接模式实现的结构图
第三种也就是我们讲的桥接模式,如果有手机品牌和软件类型的加入,只需要进行扩展就好了,之前已经写好的模块就不用修改了。
由于实现的方式是多种的,桥接模式的核心就是把这些实现独立出来,让他们自己变化。这样每种变化不会影响到其他的实现,从而达到应对变化的目的。
优点
1、抽象与实现分离,扩展能力强
2、符合开闭原则
3、符合合成复用原则
4、其实现细节对客户透明
通俗点讲就是我们的实现系统可能有多角度的分类,每种类都有可能变化,桥架模式做的就是把这些多角度独立出来,让他们可以自己变化,而不影响其他的模块,减少他们之间的藕合。
缺点
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
应用场景
1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
代码实现
还是上面手机的栗子
// 手机软件
type HandsetSoft interface {
Run() string
}
// 手机游戏
type HandsetGame struct {
}
func (hg *HandsetGame) Run() string {
return "运行手机游戏"
}
// 手机通讯录
type HandsetAddressList struct {
}
func (hg *HandsetAddressList) Run() string {
return "运行手机通讯录"
}
// 手机品牌
type HandsetBrand interface {
SetHandsetSoft(HandsetSoft)
}
// M品牌手机手机
type HandsetBrandM struct {
HandsetSoft
}
func NewHandsetBrandM() *HandsetBrandM {
return &HandsetBrandM{}
}
func (hw *HandsetBrandM) SetHandsetSoft(soft HandsetSoft) {
hw.HandsetSoft = soft
}
func (hw *HandsetBrandM) Run() string {
return "M品牌的手机-" + hw.HandsetSoft.Run()
}
// N品牌的手机
type HandsetBrandN struct {
HandsetSoft
}
func NewHandsetBrandN() *HandsetBrandN {
return &HandsetBrandN{}
}
func (ap *HandsetBrandN) SetHandsetSoft(soft HandsetSoft) {
ap.HandsetSoft = soft
}
func (ap *HandsetBrandN) Run() string {
return "N品牌的手机-" + ap.HandsetSoft.Run()
}
参考
【文中代码】https://github.com/boilingfrog/design-pattern-learning/tree/master/桥接模式
【大话设计模式】https://book.douban.com/subject/2334288/
【极客时间】https://time.geekbang.org/column/intro/100039001
【桥接模式】https://boilingfrog.github.io/2021/11/11/使用go实现桥接模式/