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

时间:2015-02-23 05:48:45

标签: python chain-of-responsibility

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

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

1 个答案:

答案 0 :(得分: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)

并处理未定义的&#39;类型,你需要一个最终的全能处理程序:

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

并将其添加到您的管道中:

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

(一个终止的UndefinedCustomer处理程序也允许你删除&#39;如果没有来自你的协同程序的代码 - 除了终止符之外都会有继承符,终结符知道它是终结符并且会不要叫继任者。)

通过这些更改,我从测试中获得此输出:

Platinum Customer
Gold Customer
No such customer type 'undefined'

另外,为什么在HandleCustomer中捕获StopIteration?这段代码应该足够了:

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