Python的结构型设计模式之桥接模式

用于将“抽象”(比如接口或算法)与实现方式相分离


一般写法:
若干基类

每个基类: 子类A 子类B 子类C


用来表示对这种抽象方法的不同实现

桥接模式:


抽象体系 定义我们所要执行的操作

实现体系 定义包含具体实现方式

抽象体系调用实现体系以完成其操作。
抽象体系中的类会把实现体系中的某个类实例聚合进来,而这个实例将充当抽象接口与具体实现之间的桥梁。
这里关键理解聚合进来是什么意思。回想之前的适配器模式,就是把一个类聚合到适配器类中,几个方法可以在一个方法中完成。   

此次的实例是编写一个类,来完成用特定算法绘制条形图,具体的算法实现放在其他类中。

这里其实和适配器模式有点类似,大家来看:

class BarCharter:

    def __init__(self, renderer):
        if not isinstance(renderer, BarRenderer):
            raise TypeError('Exception object of {}'.format(type(render).__name__))
        self.__renderer = renderer

    def render(self, caption, pairs):
        maximum = max(value for _, value in pairs)
        self.__renderer.initialize(len(pairs), maximum)
        self.__renderer.draw_caption(caption)
        for name, value in pairs:
            self.__renderer.draw_bar(name, value)
        self.__renderer.finalize()
这个类就是用来抽象体系,在初始化里面来判断传入的类型是否正确


def has_methods(*methods):
    def decorator(Base):
        def __subclasshook__(Class, Sublass):
            if Class is Base:
                attributes = collections.ChainMap(*(Superclass.__dict__ for Superclass in Sublass.__mro__))
                if all(method in attributes for method in methods)
                    return True
            return NotImplemented
        Base.__subclasshook__ = classmethod(__subclasshook__)
        return Base
    return decorator


@has_methods("initialize", "draw_caption", "dram_bar", "finalize")
class BarRenderer(metaclass=abc.ABCMeta):
    pass
而传入的类型的接口此处用了类修饰器来生成,可对比上一篇 Python的结构型设计模式之适配器模式http://blog.csdn.net/zy_dream/article/details/69934300

class TextBarRenderer:

    def __init__(self, scaleFactor=40):
        self.scaleFactor = scaleFactor

    def initialize(self, bars, maximum):
        assert bars > 0 and maximum > 0
        self.scale = self.scaleFactor / maximum

    def draw_caption(self, caption):
        print ("{0:^{2}}\n{1:^{2}}".format(caption, "=" * len(caption), self.scaleFactor))

    def draw_bar(self, name, value):
        print ("{}{}".format("*" * int(value * self.scale), name))

    def finalize(self):
        pass


class ImageBarRender:

    COLORS = [Image.color_for_name(name) for name in ("red", "green", "blue", "yellow", "magenta", "cyan")]

    def __init__(self, stepHeight=10, barWidth=30, barGap=2):
        self.stepHeight = stepHeight
        self.barWidth = barWidth
        self.barGap = barGap

    def initialize(self, bars, maximum):
        # 作图
        pass

    def draw_caption(self, caption):
        # 作图
        pass

    def draw_bar(self, name, value):
        # 作图
        pass

    def finalize(self):
        # 作图
        pass
最后就是两个实现体系的生成,因 Image 模块我暂时未安装,直接带过,但是这样好像也挺简单易懂的。


def main():
    pairs = {("Mon", 11), ("Tue", 12), ("Wed", 13), ("Thu", 17), ("Fri", 24), ("Sat", 15), ("Sun", 13)}
    textBarCharter = BarCharter(TextBarRenderer())
    textBarCharter.render("Forecast 6/8", pairs)
    imageBarCharter = BarCharter(ImageBarRender())
    imageBarCharter.render("Forecast 6/8", pairs)


if __name__ == '__main__':
    main()



通过桥接模式,是更加进一步理解了渲染接口的渲染器。render 接口里面的方法,子类里面必为相同的行为。
而如果这时候有其他一些相似功能的子类,其方法可能比接口里面的多,或者少。此时类似于上面这两个子类,就可以作为其他子类的桥梁(也就是模仿吧)进行聚合,来成为可以渲染的子类。即为桥接模式。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章