【学习设计模式10】分离抽象与实现——桥接模式

【学习设计模式10】分离抽象与实现——桥接模式_第1张图片

上篇:【学习设计模式9】兼容扩展坞—适配器模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式8】组装流水线——建造者模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式7】复制粘贴就得了——原型模式_Aiky哇的博客-CSDN博客那么有没有一种方法可以名正言顺的复制粘贴呢?当然有了,那就是原型模式。原型模式也叫克隆模式。https://aikysay.blog.csdn.net/article/details/123407658建造者模式的定义建造者模式的使用流程建造者模式的适用场景建造者模式的优缺点参考文献建造者模式(Bulider模式)详解复杂对象的组装与创建...https://aikysay.blog.csdn.net/article/details/124437201

下篇:

【学习设计模式11】树形处理——组合模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式10】分离抽象与实现——桥接模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式9】兼容扩展坞—适配器模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式8】组装流水线——建造者模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式7】复制粘贴就得了——原型模式_Aiky哇的博客-CSDN博客那么有没有一种方法可以名正言顺的复制粘贴呢?当然有了,那就是原型模式。原型模式也叫克隆模式。https://aikysay.blog.csdn.net/article/deta....https://aikysay.blog.csdn.net/article/details/125068519 

桥接模式的定义

桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。

看不懂,是吧,桥接模式的定义比较抽象,比起单例模式啊,原型模式啊那些比较明显的定义来说,桥接模式的定义确实不好理解。

更好理解的说法是,如果实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少他们之间的耦合。

桥接模式的UML

【学习设计模式10】分离抽象与实现——桥接模式_第2张图片

 分析一下角色类:

  • Abstraction:抽象类。其中定义了一个Implementor(实现类接口)类型的对象,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
  • RefinedAbstraction:扩充抽象类。通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
  • Implementor:Implementor接口会声明一些基本方法,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。
  • ConcreteImplementor:具体实现类 。 具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。

桥接模式的举例思考 

引用《大话设计模式》里的例子:

现在需要设计一个手机提供商,需要提供小米手机和华为手机两种不同的手机,每种手机需要有两个功能项,游戏功能和通讯录功能。

那么如果不考虑桥接模式,我们按照通常思路来设计:

【学习设计模式10】分离抽象与实现——桥接模式_第3张图片

按照描述来说,必然是这样设计的。

  1. 先定义一个手机品牌的抽象接口。
  2. 小米手机和华为手机算是具体实现。
  3. 然后再为小米手机和华为手机分别设计游戏和通讯录功能。

那么如果按照桥接模式来设计:

【学习设计模式10】分离抽象与实现——桥接模式_第4张图片

这样一比较,就可以看出来桥接模式的优点所在了:

  1. 分类更加合理,相对于第一种设计模式,桥接模式中,手机接口的子类就是手机,软件接口的子类就是软件,不会像第一种方式一样,几种方式混杂在一起。
  2. 组合是优于继承的,普通的设计模式,软件是继承手机的,桥接模式里,软件和手机是组合的。
  3. 桥接模式更加符合开闭原则
     

桥接模式的代码参考

使用上面的例子,使用go语言来写一下桥接模式的实现。

// Abstraction:抽象类。
// 手机类,一个方法AddSoft(),负责添加软件
type mobilePhone interface{
    isMobilePhone()
    AddSoft(Soft)
}

// RefinedAbstraction:扩充抽象类
// 小米手机类
type XiaoMiPhone struct{
    softs []Soft
}

func(n *XiaoMiPhone) isMobilePhone(){}

func(n *XiaoMiPhone) AddSoft(soft Soft) {
    n.softs=append(n.softs,soft)
}

// 华为手机类
type HuaWeiPhone struct{
    softs []Soft
}

func(n *HuaWeiPhone) isMobilePhone(){}

func(n *HuaWeiPhone) AddSoft(soft Soft) {
    n.softs=append(n.softs,soft)
}

// Implementor接口
// 软件类,一个方法Run()
type Soft interface{
    isSoft()
    Run()
}

// ConcreteImplementor:
// 游戏类
type GameSoft struct{
    //...
}

func(n *GameSoft) isSoft(){}

func(n *GameSoft) Run(){
    fmt.Println("游戏软件开始运行")
}

// 手机通讯录
type MailSoft struct{
    //...
}

func(n *MailSoft) isSoft(){}

func(n *MailSoft) Run(){
    fmt.Println("通讯软件开始运行")
}



//--------------------------------------

func main(){
    var a,b mobilePhone
    a = &XiaoMiPhone{}
    b = &HuaWeiPhone{}

    var soft1,soft2 Soft
    soft1 = &GameSoft{}
    soft2 = &MailSoft{}

    a.AddSoft(soft1)
    a.AddSoft(soft2)

    b.AddSoft(soft1)
    b.AddSoft(soft2)

    for _,i:=range a.softs{
        i.Run()
    }

    for _,i:=range b.softs{
        i.Run()
    }
}

桥接模式的优缺点与适用场景

桥接模式的优点

  1. 分离抽象接口及其实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。
  2. 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
  3. 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。

桥接模式的缺点

  1. 桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
  2. 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。

桥接模式的适用场景

在发现我们需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放-封闭原则时,就应该要考虑用桥接模式了。

  1. 如果一个系统需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。
  2. “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
  3. 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展。
  4. 对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

参考资料 

处理多维度变化——桥接模式(二)_LoveLion的博客-CSDN博客_如果系统中存在两个以上的变化维度

 Go设计模式(12)-桥接模式_程序员麻辣烫的博客-CSDN博客

处理多维度变化——桥接模式(四)_LoveLion的博客-CSDN博客

你可能感兴趣的:(go,设计模式,学习,设计模式)