Domanda

Ho due classi: Account e Operatore. L'account contiene un elenco di operatori. Ora, ogni volta che un operatore (nell'elenco) riceve un messaggio, voglio avvisare l'oggetto Account anche per eseguire alcune logiche aziendali.

Penso a tre alternative su come raggiungere questo obiettivo:

1) Mantenere un riferimento all'interno dell'Operatore sull'oggetto contenitore [Account] e chiamare direttamente i metodi. Non assolutamente buono a causa di riferimenti circolari.

2) Usa eventi. Per quanto ne so non esiste un meccanismo di gestione degli eventi integrato in Python. Quindi, questo è un po 'complicato da implementare.

3) Non inviare messaggi direttamente agli Operatori. Invece, gestisci solo gli Account e al loro interno, gli operatori dei gestori. Questo è un po 'limitante perché in questo caso non riesco a passare i riferimenti agli operatori.

Mi chiedo quale approccio sia il più vantaggioso dal punto di vista architettonico. Come di solito gestisci questa attività?

Sarebbe bello se potessi indicare snippet in Python.

È stato utile?

Soluzione

Stai pensando troppo. Sul serio. Python non è C ++; le tue preoccupazioni sono non-problemi in Python. Scrivi ciò che ha senso nel tuo dominio problematico.

" Non assolutamente buono a causa di riferimenti circolari. & Quot;

Perché no? La circolarità non ha alcuna rilevanza qui. Le relazioni bidirezionali sono grandi cose. Usali. La spazzatura di Python li raccoglie bene senza pensare da parte tua.

Quale possibile problema hai con le relazioni reciproche (birectional)?

" ... gestiscono solo account e al loro interno gestori di gestori. Questo è un po 'limitante perché in questo caso non riesco a passare i riferimenti agli operatori. & Quot;

Che cosa? I tuoi operatori sono oggetti Python, passa tutto quello che vuoi. Tutti gli oggetti Python sono (in effetti) riferimenti, non sudare.

Quale possibile problema hai con la manipolazione di oggetti Operator?

Altri suggerimenti

Non esiste " taglia unica per tutte " soluzione per il modello Observer. Ma di solito, è meglio definire un oggetto EventManager in cui le parti interessate possono registrarsi per determinati eventi e pubblicare tali eventi ogni volta che si verificano. Crea semplicemente meno dipendenze.

Si noti che è necessario utilizzare un'istanza globale di EventManager, che può essere problematica durante il test o da un punto di vista OO generale (è una variabile globale). Consiglio vivamente di non passare l'EventManager in continuazione perché ciò ingombrerà il tuo codice.

Nel mio codice, la chiave " " per la registrazione degli eventi è la classe dell'evento. EventManager utilizza un dizionario (classe di eventi - > elenco di osservatori) per sapere quale evento va dove. Nel codice di notifica, puoi quindi utilizzare dict.get (event .__ class__, ()) per trovare i tuoi ascoltatori.

Userei la gestione degli eventi per questo. Non è necessario implementarlo da solo: utilizzo pydispatcher per questo tipo di gestione degli eventi e ha sempre funzionato molto bene (usa riferimenti deboli internamente, per evitare il problema dei riferimenti circolari).

Inoltre, se stai usando un framework gui, potresti già avere un framework di eventi a cui puoi agganciarti, ad esempio PyQt ha segnali e slot.

>>> class Account(object):
...     def notify(self):
...         print "Account notified"
...
>>> class Operator(object):
...     def __init__(self, notifier):
...         self.notifier = notifier
...
>>> A = Account()
>>> O = Operator(A.notify)
>>> O.notifier()
Account notified
>>> import gc
>>> gc.garbage
[]
>>> del A
>>> del O
>>> gc.garbage
[]

Una cosa che potresti non sapere sui metodi di istanza è che sono associati quando vengono cercati quando si utilizza la sintassi del punto. In altre parole, dicendo A.notify associa automaticamente il parametro di sé della notifica ad A. Puoi quindi mantenere un riferimento a questa funzione senza creare immondizia non raccoglibile.

Infine, puoi sempre utilizzare Kamaelia per questo tipo di cose.

Esistono frammenti di pattern Observer in tutto il Web. Una buona fonte di codice affidabile è lo stato attivo, E.G:

http://code.activestate.com/recipes/131499/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top