Python设计模式——桥接模式

桥接模式(Bridge Pattern)用于将”抽象”(abstraction, 比如接口或算法)与实现方式相分离。

如果不用桥接模式,那么通常的写法是,创建若干个基类,用于表示各种抽象方式,然后从每个基类中继承出两个或多个子类,用于表示对这种抽象方式的不同实现办法。用了桥接模式之后,我们需要创建两套独立的”类体系”:“抽象体系”定义了我们要执行的操作(比如接口或高层算法),而”实现体系”则包含具体实现方式,抽象体系要调用实体体系以完成其操作。抽象体系中的类会把实现体系中的某个类实例聚合起来,而这个实例将充当抽象接口与具体实现之间的桥梁(bridge)。

本文算是《Python编程实战》的摘要了

#!/usr/bin/env python
# encoding: utf-8

import abc
import os
import re
import tempfile
import Tkinter as tk

def has_methods(*methods):
    """
        类修饰器,功能判断*methods是否存在于类中,
        使用abc中的__subclasshook__实现
    """
    def decorator(Base):
        def __subclasshook__(Class, Subclass):
            if Class is Base:
                needed = set(methods)
                for Superclass in Subclass.__mro__:
                    for meth in needed.copy():
                        if meth in Superclass.__dict__:
                            needed.discard(meth)
                    if not needed:
                        return True
            return NotImplemented
        Base.__subclasshook__ = classmethod(__subclasshook__)
        return Base
    return decorator

@has_methods('initialize', 'draw_caption', 'draw_bar', 'finalize')
class BarRenderer(object):
    __metaclass__ = abc.ABCMeta

class BarCharter(object):
    def __init__(self, renderer):
        if not isinstance(renderer, BarRenderer):
            raise TypeError('is not BarCharter')
        self.__renderer = renderer

    def render(self, caption, pairs):
        maximux = max(value for _, value in pairs)
        self.__renderer.initialize(len(pairs), maximux)
        self.__renderer.draw_caption(caption)
        for name, value in pairs:
            self.__renderer.draw_bar(name, value)
        self.__renderer.finalize()

class TextBarRenderer(object):
    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 ImageBarRenderer(object):
    COLORS = ('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):
        assert bars > 0 and maximum > 0
        if tk._default_root is None:
            self.gui = tk.Tk()
            self.inGui = False
        else:
            self.gui = tk._default_root
            self.inGui = True
        self.index = 0
        self.width = bars * (self.barWidth + self.barGap)
        self.height = maximum * self.stepHeight
        self.image = tk.PhotoImage(width=self.width, height=self.height)
        self.image.put("white", (0, 0, self.width, self.height))

    def draw_caption(self, caption):
        self.filename = os.path.join(tempfile.gettempdir(),
                re.sub(r"\W+", "_", caption) + ".gif")


    def draw_bar(self, name, value):
        color = ImageBarRenderer.COLORS[self.index %
                len(ImageBarRenderer.COLORS)]
        x0 = self.index * (self.barWidth + self.barGap)
        x1 = x0 + self.barWidth
        y0 = self.height - (value * self.stepHeight)
        y1 = self.height - 1
        self.image.put(color, (x0, y0, x1, y1))
        self.index += 1


    def finalize(self):
        self.image.write(self.filename, "gif")
        print("wrote", self.filename)
        if not self.inGui:
            self.gui.quit()

def main():
    pairs = (('Mon', 16), ('Tue', 17), ('Wed', 19),
            ('Thu', 22), ('Fri', 24), ('Sat', 21),
            ('Sun', 19))
    textBarCharter = BarCharter(TextBarRenderer())
    textBarCharter.render('Forecast 6/8', pairs)
    imageBarCharter = BarCharter(ImageBarRenderer())
    imageBarCharter.render('Forecase 6/8', pairs)

if __name__ == '__main__':
    main()

TextBarRendererfinalize()什么事没做,但还是必须写上,因为条形图渲染器的接口里定义了这个方法

上面代码中尽管TextBarRendererImageBarRenderer的实现方式差别很大,但它们均可作为抽象体系与实现体系之间的桥梁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值