2015-02-23 70 views
5

我正在探索python中的不同概念,並且偶然發現了一個可用於責任設計模式鏈的協程的例子。我寫了下面的代碼:在python中使用協同程序實現責任鏈模式

from functools import wraps 

def coroutine(function): 
    @wraps(function) 
    def wrapper(*args, **kwargs): 
     generator = function(*args, **kwargs) 
     next(generator) 
     return generator 
    return wrapper 

@coroutine 
def PlatinumCustomer(successor=None): 
    cust = (yield) 
    if cust.custtype == 'platinum': 
     print "Platinum Customer" 
    elif successor is not None: 
     successor.send(cust) 

@coroutine 
def GoldCustomer(successor=None): 
    cust = (yield) 
    if cust.custtype == 'gold': 
     print "Gold Customer" 
    elif successor is not None: 
     successor.send(cust) 

@coroutine 
def SilverCustomer(successor=None): 
    cust = (yield) 
    if cust.custtype == 'silver': 
     print "Silver Customer" 
    elif successor is not None: 
     successor.send(cust) 

@coroutine 
def DiamondCustomer(successor=None): 
    cust = (yield) 
    if cust.custtype == 'diamond': 
     print "Diamond Customer" 
    elif successor is not None: 
     successor.send(cust) 

class Customer: 
    pipeline = PlatinumCustomer(GoldCustomer(SilverCustomer(DiamondCustomer()))) 

    def __init__(self,custtype): 
     self.custtype = custtype 

    def HandleCustomer(self): 
     try: 
      self.pipeline.send(self) 
     except StopIteration: 
      pass 

if __name__ == '__main__': 
    platinum = Customer('platinum') 
    gold = Customer('gold') 
    silver = Customer('silver') 
    diamond = Customer('diamond') 
    undefined = Customer('undefined') 

    platinum.HandleCustomer() 
    gold.HandleCustomer() 
    undefined.HandleCustomer() 

我試圖做的,是儘量創造的責任模式解決方案鏈處理不同類型的客戶(白金,黃金,鑽石,銀)的。

對於該客戶有一個管道,我已經提到了處理不同客戶的順序。 Customer()。HandleCustomer將通過流水線發送一個實例,它將檢查它的custtype是否匹配,然後相應地處理它,或者將它發送到其後繼者(如果可用)

問題:問題是,我運行上面的腳本,它將處理第一個白金客戶,但不是黃金或未定義的。我假設這是因爲他已經到達發電機的末端。我如何修改代碼,以便每次它是客戶的新實例時,都會從頭開始通過管道?

回答

4

你的協同程序必須永遠循環下去,以處理後續的調用,如:

@coroutine 
def PlatinumCustomer(successor=None): 
    while 1: # <---- this is missing from your coroutines 
     cust = (yield) 
     if cust.custtype == 'platinum': 
      print "Platinum Customer" 
     elif successor is not None: 
      successor.send(cust) 

,並處理了「未定義」類型,你需要一個最終的包羅萬象的處理程序:

@coroutine 
def UndefinedCustomer(): 
    while 1: 
     cust = (yield) 
     print "No such customer type '%s'" % cust.custtype 

,並把它添加到您的管道:

pipeline = PlatinumCustomer(GoldCustomer(SilverCustomer(DiamondCustomer(UndefinedCustomer())))) 

(A終止UndefinedCustomer處理程序也將讓您從協同工作中刪除'如果沒有後繼'代碼 - 除終止符外,它們都將有後繼者,它們知道它是終止符,不會稱爲後繼符。)

有了這些更改,我可以得到這個從你的測試輸出:

Platinum Customer 
Gold Customer 
No such customer type 'undefined' 

此外,爲什麼在HandleCustomer捕獲StopIteration?這個代碼應該是足夠的:

def HandleCustomer(self): 
    self.pipeline.send(self) 
+0

工程就像一個魅力。 – Rivas 2015-02-23 09:18:24

+0

我很抱歉無法投票。我沒有足夠的聲譽。 – Rivas 2015-02-23 09:18:59