Python设计模式——责任链模式

来源:互联网 发布:淘宝首页psd模板教程 编辑:程序博客网 时间:2024/06/07 05:11

责任链模式(Chain of Responsibility Pattern)可将请求的发送方与处理请求的接收方解耦。这样的话,某函数就不用直接调用别的函数了,而是可以把请求发送给一个由诸多接收者所组成的链条。链条中的首个接收者可以处理请求并停止责任链(也就是不再继续往下传递),也可以把请求发给下一个接收者。而第二个接收者也有这两种选择,此过程可一直延续至最后一个接收者,该接收者可将请求丢弃,也可抛出异常。

使用常规方法实现

#!/usr/bin/env python# encoding:utf-8class NullHandler(object):    def __init__(self, successor=None):        self.__successor = successor    def handle(self, event):        if self.__successor is not None:            self.__successor.handle(event)class ConcreteHandler1(NullHandler):    def handle(self, event):        if event > 0 and event <= 10:            print "in handler1", event        else:            super(ConcreteHandler1, self).handle(event)class ConcreteHandler2(NullHandler):    def handle(self, event):        if event > 10 and event <= 20:            print "in handler2", event        else:            super(ConcreteHandler2, self).handle(event)class ConcreteHandler3(NullHandler):    def handle(self, event):        if event > 20 and event <= 30:            print "in handler3", event        else:            super(ConcreteHandler3, self).handle(event)def main():    handler = ConcreteHandler3(ConcreteHandler2(ConcreteHandler1(NullHandler())))    events = [2, 5, 14, 22, 18, 3, 35, 27, 20]    for event in events:        handler.handle(event)

所示代码在NullHandler设置一个successor属性,使用它来执行handle,而其他则继承NullHandler,这样不符合自身条件将它抛给NullHandler,让它来执行successorhandle。我们可以从上面赋值中看出successor的顺序,一开始最里面successorNone,后面是ConcreteHandler1类型…依次类推,实现责任链。

使用协程实现责任链

关于协程

协程(coroutine)与生成器一样,也使用yield表达式,但行为不同。协程执行的是无限循环,而且一开始就会停在首个(或仅有的那个)yield表达式那里,等值有值传给它。协程会把收到的值当成yield表达式的值,然后继续执行它所需的操作,等处理完之后,又会再度循环,并在下一个yield表达式那里等着接收下个值。这样的话,我们就能反复调用协程中的send()throw()方法向其push值。
在Python中,凡是带有yield语句的函数或方法都能充当生成器。而利用@coroutine装饰器及无限循环则可将生成器变为协程。

import functoolsdef coroutine(function):    @functools.wraps(function)    def wrapper(*args, **kwargs):        generator = function(*args, **kwargs)        next(generator)#调用一次生成器,令生成器对象前进到首个yield表达式。        return generator    return wrapper
#!/usr/bin/env python# encoding:utf-8@coroutinedef mouse_handler(successor=None):    while True:        event = (yield)        if 0 < event <= 10:            print("mouse-num:   {}".format(event))        elif successor is not None:            successor.send(event)@coroutinedef key_handler(successor=None):    while True:        event = (yield)        if 10 < event <= 20:            print("key-num:   {}".format(event))        elif successor is not None:            successor.send(event)@coroutinedef timer_handler(successor=None):    while True:        event = (yield)        if 20 < event <= 30:            print("timer-num: {}".format(event))        elif successor is not None:            successor.send(event)def main():    pipeline = key_handler(mouse_handler(timer_handler()))    events = [2, 5, 14, 22, 18, 3, 35, 27, 20]    for event in events:        pipeline.send(event)if __name__ == "__main__":    main()
0 0
原创粉丝点击