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 接口裏面的方法,子類裏面必爲相同的行爲。
而如果這時候有其他一些相似功能的子類,其方法可能比接口裏面的多,或者少。此時類似於上面這兩個子類,就可以作爲其他子類的橋樑(也就是模仿吧)進行聚合,來成爲可以渲染的子類。即爲橋接模式。



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