Python設計模式——責任鏈模式

責任鏈模式(Chain of Responsibility Pattern)可將請求的發送方與處理請求的接收方解耦。這樣的話,某函數就不用直接調用別的函數了,而是可以把請求發送給一個由諸多接收者所組成的鏈條。鏈條中的首個接收者可以處理請求並停止責任鏈(也就是不再繼續往下傳遞),也可以把請求發給下一個接收者。而第二個接收者也有這兩種選擇,此過程可一直延續至最後一個接收者,該接收者可將請求丟棄,也可拋出異常。

使用常規方法實現

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

class 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 functools

def 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

@coroutine
def 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)


@coroutine
def 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)


@coroutine
def 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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章