Pregunta

Tengo dos clases: Cuenta y Operador. Cuenta contiene una lista de operadores. Ahora, cada vez que un operador (en la lista) recibe un mensaje, deseo notificar al objeto de la Cuenta para que también realice alguna lógica de negocios.

Pienso en tres alternativas sobre cómo lograr esto:

1) Mantenga una referencia dentro del Operador al objeto [Cuenta] del contenedor y llame a los métodos directamente. No es absolutamente bueno debido a las referencias circulares.

2) Usa eventos. Por lo que sé, no hay un mecanismo integrado de manejo de eventos en Python. Por lo tanto, este es un poco difícil de implementar.

3) No envíe mensajes a los operadores directamente. En su lugar, opere solo Cuentas, y dentro de ellas, internamente, operadores manejadores. Este es un poco limitante porque en este caso no puedo pasar las referencias a los operadores.

Me pregunto qué enfoque es el más ventajoso desde el punto de vista arquitectónico. ¿Cómo suele manejar esta tarea?

Sería genial si pudieras señalar fragmentos en Python.

¿Fue útil?

Solución

Estás pensando demasiado en esto. Seriamente. Python no es C ++; Sus preocupaciones no son problemáticas en Python. Solo escribe lo que tenga sentido en tu dominio de problema.

" No es absolutamente bueno debido a las referencias circulares. & Quot;

¿Por qué no? La circularidad no tiene ninguna importancia aquí en absoluto. Las relaciones bidireccionales son grandes cosas. Usalos, usalos a ellos. La basura de Python los recolecta sin ningún pensamiento de tu parte.

¿Qué posible problema tiene con las relaciones mutuas (bireccionales)?

" ... opera solo cuentas, y dentro de ellas, internamente, operadores manejadores. Este es un poco limitante porque en este caso no puedo pasar las referencias a los operadores. "

¿Qué? Tus operadores son objetos de Python, pasa todo lo que quieras. Todos los objetos de Python son referencias (en efecto), no se preocupen.

¿Qué posible problema tiene con la manipulación de los objetos del operador?

Otros consejos

No hay un " talla única para todos " Solución para el patrón Observer. Pero, por lo general, es mejor definir un objeto EventManager donde las partes interesadas pueden registrarse para ciertos eventos y publicar estos eventos cuando suceden. Simplemente crea menos dependencias.

Tenga en cuenta que necesita usar una instancia global de EventManager, que puede ser problemática durante las pruebas o desde un punto de vista general de OO (es una variable global). Aconsejo encarecidamente que no se pase el EventManager todo el tiempo porque eso saturará tu código.

En mi propio código, la tecla " " Para registrar eventos es la clase del evento. EventManager usa un diccionario (clase de evento - > lista de observadores) para saber qué evento va a dónde. En el código de notificación, puede usar dict.get (evento .__ clase__, ()) para encontrar a sus oyentes.

Yo usaría el manejo de eventos para esto. No tiene que implementarlo usted mismo, uso pydispatcher para exactamente este tipo de manejo de eventos, y siempre ha funcionado muy bien (usa referencias débiles internamente, para evitar el problema de referencia circular).

Además, si está utilizando un marco gui, es posible que ya tenga un marco de eventos al que pueda enlazar, por ejemplo, PyQt tiene señales y ranuras.

>>> 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 que quizás no sepas acerca de los métodos de instancia es que están vinculados cuando se buscan al usar la sintaxis de puntos. En otras palabras, decir A.notify vincula automáticamente el parámetro automático de notificar a A. A continuación, puede mantener una referencia a esta función sin crear basura no recolectable.

Por último, siempre puedes usar Kamaelia para este tipo de cosas.

Hay fragmentos de patrones de Observer en toda la Web. Una buena fuente de código confiable es el estado activo, E.G:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top