资讯专栏INFORMATION COLUMN

python设计模式-桥接模式&比较桥接模式和装饰模式的不同

quietin / 2797人阅读

摘要:桥接模式和装饰模式的区别设计模式装饰模式桥接模式和装饰模式都是通过将继承关系转换为关联关系从而减少系统中类的数量,降低系统的耦合性。装饰器模式支持多层装饰,通过不同的组合可以实现不同的行为。

产生桥接模式的动机:

假设这样一种情况:
我们有大中小型号的毛笔,有红蓝黑三种颜料。如果需要不同颜色,不同型号的毛笔有如下两种设计方法:

为每一种型号的毛笔都提供三种颜料的版本。

将毛笔和颜料分开,使用的时候自由组合。

针对第一种我们当下就需要红色颜料大号毛笔、蓝色颜料大号毛笔等九中型号,在之后的扩展中,每增加一个型号的毛笔就需要为其增加所有颜料的版本, 而每增加一种颜料也需要为所有的笔增添新的颜料类型。随着笔的类型和颜料种类的不断增长,其类数量的增加速度为O(n!) 我们需要维护庞大的种类集合。
而第二种我们将笔和颜料分开,就比如说准备大中小三种型号的毛笔,以及红蓝黑三种颜料,用的时候就拿笔区蘸一下颜料就可以,这样笔和颜料解耦,他们可以分开增加。其类的增加速度为O(n) 我们可以看出 O(n!)的增长速度远大于O(n)。

第一种方法在系统设计上我们采用的就是继承的方式。实现方式上有两种,一种就像我上面提到的只有一个抽象类,然后所有子类都是由这个抽象类里面派生出来了,还有一种代码编写方式就是提供毛笔抽象类和颜料抽象类 以及他们的派生子类,然后子类使用多继承分别继承他们,这种编写方式又一个问题就是在不支持多继承的语言中无法实现(例子请看我的 文章中的那一部分。)

第二种方法是采用组合关系的设计,其设计中也是将颜料和笔这两个变化分开,及分别由笔的抽象类派生出各种各样的笔和由颜料抽象类派生出的各种各样的颜料。但是将他们之间连接在一起的是关联关系方式(不懂的可以区我的这一篇文章看一下)。在结构型设计模式中大量使用这种关联关系来代替继承关系以实现解耦,为什么关联关系可以解耦呢?我认为主要有以下几点:

继承关系中,父类的修改会传播到子类中,容易造成子类的不稳定。

继承关系在代码编写阶段已经固定,但是使用关联关系,我们可以将他们之间的关系确定推迟到程序运行时,更加方便用户控制。比如使用配置文件来确定关联关系中的两个类的类型。

使用关联关系也可以减少代码的编写量,尤其是在变化的种类很多以及后期增加种类的时候。

使用关联关系在后期增加变化种类,不需要更改已经存在的类。满足开闭原则

使用关联关系也将功能分割,符合单一职责原则

桥接模式的定义:

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

实现 使用继承方式的实现 UML类图

python 代码
class BrushAbstraction(object):
    def __init__(self, size, color):
        self.paint = None
        self.__size = size
        self.__color = color

    def draw(self):
        print("Use {} {} brush draw".format(self.__color, self.__size))


class BigBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(BigBrushAbstration, self).__init__("Big", color)


class MiddleBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(MiddleBrushAbstration, self).__init__("Middle", color)


class SmallBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(SmallBrushAbstration, self).__init__("Small", color)


class RedBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(RedBigBrushAbstration, self).__init__("Red")


class BlueBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(BlueBigBrushAbstration, self).__init__("Blue")


class BlackBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(BlackBigBrushAbstration, self).__init__("Black")


class RedMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(RedMiddleBrushAbstration, self).__init__("Red")


class BlueMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(BlueMiddleBrushAbstration, self).__init__("Blue")


class BlackMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(BlackMiddleBrushAbstration, self).__init__("Black")


class RedSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(RedSmallBrushAbstration, self).__init__("Red")


class BlueSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(BlueSmallBrushAbstration, self).__init__("Blue")


class BlackSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(BlackSmallBrushAbstration, self).__init__("Black")


if __name__ == "__main__":
    blue_big_brush = BlueBigBrushAbstration()
    blue_big_brush.draw()

    black_big_brush = BlackBigBrushAbstration()
    black_big_brush.draw()
使用桥接模式重构后 UML类图

代码
class BrushAbstraction(object):
    def __init__(self, size):
        self.paint = None
        self.__size = size

    def dip_paint(self, paint):
        self.paint = paint

    def draw(self):
        print("Use {} {} brush draw".format(self.paint.color(), self.__size))


class BigBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(BigBrushAbstration, self).__init__("Big")


class MiddleBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(MiddleBrushAbstration, self).__init__("Middle")


class SmallBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(SmallBrushAbstration, self).__init__("Small")


class PaintImplementer(object):
    def __init__(self, color):
        self.__color = color

    def color(self):
        return self.__color


class RedPaintImplementer(PaintImplementer):
    def __init__(self):
        super(RedPaintImplementer, self).__init__("Red")


class BluePaintImplementer(PaintImplementer):
    def __init__(self):
        super(BluePaintImplementer, self).__init__("Blue")


class BlackPaintImplementer(PaintImplementer):
    def __init__(self):
        super(BlackPaintImplementer, self).__init__("Black")


if __name__ == "__main__":
    big_bursh = BigBrushAbstration()
    big_bursh.dip_paint(BluePaintImplementer())
    big_bursh.draw()

    big_bursh.dip_paint(BlackPaintImplementer())
    big_bursh.draw()
代码分析

在上面的继承方式的实现中我们采用的是单继承,在我的python设计模式-装饰模式采用继承方式就是多继承。桥接模式有时类似多继承方法。不过桥接模式产生了很多不同的小对象而多继承方案产生了很多不同的小类。但是多继承方案违背了类的单一职责原则(即一个类只应该有一个变化的原因),其次多继承关系的确定在编码阶段就已经确定,无法灵活的扩展,还有就是很多语言是不支持多继承的。

桥接模式的优缺点 优点

分离了抽象接口与实现部分

提高系统可扩充性,在两个纬度中任意扩展,都不需对原系统进行修改。

缺点

桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。 - 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。

适用环境

如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。

抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。

一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。

对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

桥接模式和装饰模式的区别

python设计模式-装饰模式

桥接模式和装饰模式都是通过将继承关系转换为关联关系从而减少系统中类的数量,降低系统的耦合性。

桥接模式是解决一个系统有多个变化维度的一种设计模式。其难点是如何将其中的抽象化与实现化分离(抽象化是指将一组复杂物体的一个或几个特征抽取出来形成共用部分,在面向对象的程序设计中就是将对象共同的性质抽取出去而形成类的过程。实现化是指给出抽象化中的具体实现,他是对抽象化的建进一步具体化)。使用关联关系在运行时设置不同的具体类来让同一个抽象对象表现出不同的行为。在整个过程中抽象化的类其实是不稳定的,不稳定指我们通过传入不同的实现类改变了抽象类本身的运行结果。

装饰器模式是解决如何给一个类动态增加职责的一种设计模式。装饰器模式通过将一个类中需要动态执行的方法抽取出来形成装饰类,通过关联关系来将职责的添加推迟到了程序运行时。如果程序支持反射还可以通过配置文件来灵活更改对象的功能。装饰器模式支持多层装饰,通过不同的组合可以实现不同的行为。在整个过程中被装饰对象是稳定的。因为装饰模式是在被装饰对象的前后增加功能,而不是改变被装饰对象本身的功能。具体的装饰类和被装饰类可以独立变化,用户根据需要动态的增加装饰类和被装饰类,并在调用的时候进行组合,无需更改之前的代码,符合开闭原则。

从实现上看桥接模式中抽象类只包含一个实现类的引用,实现对实现类的调用。而装饰模式中抽象装饰类继承构件抽类类,并且还包含一个对抽象构建的引用。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44497.html

相关文章

  • 设计模式在jdk中应用

    摘要:本文只是寻找设计模式在中的应用。来补全这一块工厂模式中的应用包线程池解释和代码线程池中有线程创建工厂。状态模式中的应用解释和代码根据一个指针的状态而改变自己的行为适配器模式中的应用解释和代码将一个类的接口转换成客户希望的另外一个接口。 前言 最近重学设计模式,而且还有很多源码要看。所以就想一举两得。从源码中寻找设计模式。顺便还可以看看源码。。。本文只是寻找设计模式在java中的应用。优...

    dingding199389 评论0 收藏0
  • 前端设计模式

    摘要:作为一个前端新人,学习了设计模式以后,希望能从源头上,用浅显易懂的语言来解释它。创建型设计模式创建型设计模式故名思意,这些模式都是用来创建实例对象的。这就是简单工厂模式。这就是工厂方法模式。 作为一个前端新人,学习了设计模式以后,希望能从源头上,用浅显易懂的语言来解释它。当然不一定是正确的,只是我个人对设计模式的一点浅显理解。 创建型设计模式 创建型设计模式:故名思意,这些模式都是用来...

    newsning 评论0 收藏0
  • 桥接&组合

    摘要:桥接实现的时候桥接模式非常有用可能正是由于这个该模式使用地不够广泛在设计时该模式可以弱化与使用它的类和对象之间的耦合该模式的作用在于将抽象与其实现隔离开让他们独立变化而且对于事件驱动编程有许多好处有以及其他基于动作的方法无论它们是用来创建鼓 桥接 实现 API 的时候,桥接模式非常有用,可能正是由于这个,该模式使用地不够广泛.在设计 js API 时,该模式可以弱化API 与使用它的类...

    yuanxin 评论0 收藏0
  • python设计模式-装饰模式

    摘要:这种模式我们称之为装饰器模式。因为装饰器模式是在给对象增加责任。以下情况适合使用装饰器模式在不影响其他对象的情况下,以动态透明的方式给单个对象添加职责。 前言 本篇的装饰器模式不是讲解的python中的语法糖 @ 这个装饰器。而是讲解设计模式中的装饰器模式。网上很多的实现都是基于java和c++的。本文则使用python来实现,其中有些实现可能在python并不需要那样来写的,但是思路...

    Yuqi 评论0 收藏0
  • 一起学设计模式 - 桥接模式

    摘要:桥接模式属于结构型模式的一种,用于把抽象化与实现化解耦,使得二者可以独立变化,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。相关模式装饰模式与桥接模式在一定程度上都是为了减少子类的数目,避免出现复杂的继承关系。 桥接模式(Brideg Pattern)属于结构型模式的一种,用于把抽象化与实现化解耦,使得二者可以独立变化,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解...

    tinysun1234 评论0 收藏0

发表评论

0条评论

quietin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<