在python中使用协同程序实现责任链模式

问题描述:

我正在探索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是否匹配,然后相应地处理它,或者将它发送到其后继者(如果可用)

问题:问题是,我运行上面的脚本,它将处理第一个白金客户,但不是黄金或未定义的。我假设这是因为他已经到达发电机的末端。我如何修改代码,以便每次它是客户的新实例时,都会从头开始通过管道?

你的协同程序必须永远循环下去,以处理后续的调用,如:

@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