2010-09-20 20 views
14

Normalmente, en Java, cuando tengo un objeto que proporciona algún tipo de notificación a otros objetos, emplearé el patrón Listener/Observer.Scala Listener/Observer

¿Hay alguna forma más de Scala de hacer esto? ¿Debo usar este patrón en Scala, o hay algo más en el lenguaje que debería aprovechar?

Respuesta

18

Aún puede acumular una lista de devoluciones de llamada, pero puede simplemente hacer que funcionen en lugar de tener que crear otra interfaz de método única.

p. Ej.

case class MyEvent(...) 

object Foo { 
    var listeners: List[MyEvent =>()] = Nil 

    def listen(listener: MyEvent =>()) { 
    listeners ::= listener 
    } 

    def notify(ev: MyEvent) = for (l <- listeners) l(ev) 
} 

también leyeron this somewhat-related paper si se siente como tomar la píldora roja. :)

+5

y se puede extraer esta muy bien en un rasgo 'Publisher'. –

17

¿Hay una forma más de Scala de hacer esto?

Sí. Lea el documento Deprecating the Observer Pattern de Ingo Maier, Tiark Rompf y Martin Odersky.

Actualización 27-Apt-2015: También hay una más reciente Deprecating the Observer Pattern with Scala.React por Maier y Odersky.

+0

¿Podría darnos un ejemplo de esto? – cdmckay

+0

@cdmckay El paquete 'scala.swing' en la biblioteca estándar se basa en él. Vea sus ejemplos y tutoriales. –

3
trait Observer[S] { 
    def receiveUpdate(subject: S); 
} 

trait Subject[S] { 
    this: S => 
    private var observers: List[Observer[S]] = Nil 
    def addObserver(observer: Observer[S]) = observers = observer :: observers 

    def notifyObservers() = observers.foreach(_.receiveUpdate(this)) 
} 

Este fragmento es bastante similar al que se encontraría en Java con algunas funciones de Scala. Esto es del blog de Dean Wampler: http://blog.objectmentor.com/articles/2008/08/03/the-seductions-of-scala-part-i

Esto usa algunas funciones de Scala como los genéricos indicados por [S], rasgos que son como las interfaces Java pero más poderosos, :: para anteponer a un observador a la lista de observadores, y un foreach con el parámetro usando un _ que evalúa al observador actual.

2

Usted puede utilizar scala.collection.mutable.Publisher y scala.collection.mutable.Subscriber para crear un pub/sub aplicación

+0

He intentado esto una vez ... – ziggystar

+0

@ziggystar, y? ¿Cuál fue tu experiencia? – Haakon

+0

Creo que no lo hice funcionar o que era molesto de usar. Ahora estoy usando bibliotecas de terceros o haciendo mi propia cuenta. – ziggystar