2015-02-23 13 views
5

Sto esplorando diversi concetti in python e mi è capitato di leggere un esempio di coroutine che può essere utilizzato per il modello di catena della responsabilità. Ho scritto il seguente codice:Implementazione del pattern Chain of responsibility in python usando le coroutine

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

Quello che ho cercato di fare qui è cercare di creare una catena di soluzione di modello di responsabilità per la gestione di diversi tipi di clienti (Platino, oro, diamanti, argento).

Per quel cliente ha una pipeline in cui ho menzionato l'ordine in cui verranno gestiti i diversi clienti. Cliente(). HandleCustomer invierà un'istanza di sé attraverso la pipeline che verificherà se il suo custtype corrisponde e quindi elaborarlo di conseguenza o lo invierà al suo successore (se disponibile)

PROBLEMA: il problema è che quando Corro lo script sopra, gestirà il primo cliente platino ma non l'oro o il non definito. Suppongo che questo sia dovuto al fatto che ha raggiunto la fine del generatore. Come posso modificare il codice in modo che ogni volta che si tratta di una nuova istanza di un cliente, passerà attraverso la pipeline dal suo inizio?

risposta

4

I suoi co-routine deve effettuare il ciclo per sempre al fine di gestire le chiamate successive, come in:

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

E per gestire il tipo 'undefined', avrete bisogno di un finale di catch-all handler:

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

e aggiungerlo alla vostra pipeline:

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

(Un gestore UndefinedCustomer di terminazione anche vi permetterà per rimuovere il codice "se non ci sono successori" dalle tue coroutine - tutti avranno successori tranne il terminatore, che sa che è il terminatore e non chiamerà un successore.)

Con questi cambiamenti, ottengo questo uscita dai test:

Platinum Customer 
Gold Customer 
No such customer type 'undefined' 

Inoltre, perché il fermo per StopIteration in HandleCustomer? Questo codice dovrebbe essere sufficiente:

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

Funziona come un fascino. – Rivas

+0

Mi scuso per non essere stato in grado di alzare la voce. Non ho abbastanza reputazioni. – Rivas

Problemi correlati