Implementing chain of responsibility in python with coroutines

I learn various concepts in python, and I happened to read an example of coroutines that can be used for the responsibility chain design pattern. I wrote the following code:

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() 

What I tried to do here is try to create a responsibility chain template solution to handle different types of customers (Platinum, Gold, Diamond, Silver).

There is a pipeline for this client, where I mentioned the order in which different clients will be processed. Client(). HandleCustomer will send the instance itself along the pipeline, which will check whether its custtype matches, and then process it accordingly or send it through its successor (if any)

PROBLEM: The problem is that when you run the above script, it processes the first platinum client, but not gold or undefined. I guess this is because he reached the end of the generator. How can I change the code so that every time it is a new instance of the client, it will go through the pipeline from the very beginning?

+5
source share
1 answer

Your coroutines must be executed forever to handle consecutive calls, for example:

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

And to process the type 'undefined, you need the last catch-all handler:

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

and add it to your pipeline:

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

(The UndefinedCustomer end handler will also allow you to remove the "if successor code" code from your coroutines - everyone will have successors, except for the terminator, who knows that he is a terminator and will not name the successor.)

With these changes, I get this result from your tests:

 Platinum Customer Gold Customer No such customer type 'undefined' 

Also, why catch for StopIteration in HandleCustomer? This code should be sufficient:

 def HandleCustomer(self): self.pipeline.send(self) 
+4
source

Source: https://habr.com/ru/post/1213955/


All Articles