Scala Слушатель/Наблюдатель
Как правило, на Java, когда у меня есть объект, который предоставляет какое-то уведомление другим объектам, я использую шаблон Listener/Observer.
Есть ли способ Scala-like? Должен ли я использовать этот шаблон в Scala, или есть что-то еще, испеченное на языке, который я должен использовать?
Ответы
Ответ 1
Вы все еще можете скопировать список обратных вызовов, но вы можете просто сделать их функциями вместо того, чтобы придумать еще один интерфейс метода.
например.
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)
}
Также прочитайте это эту несколько связанную бумагу, если вам хочется взять красную таблетку.:)
Ответ 2
Есть ли более Scala -подобный способ сделать это?
Да. Прочтите статью Устаревший шаблон наблюдателя Инго Майера, Тирка Ромфа и Мартина Одерского.
Обновление 27-Apt-2015: Также существует более поздняя Устранение шаблона наблюдателя с помощью Scala.React Майер и Одерский.
Ответ 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))
}
Этот фрагмент довольно похож на тот, который можно найти в Java с некоторыми функциями Scala. Это из блога Dean Wampler - http://blog.objectmentor.com/articles/2008/08/03/the-seductions-of-scala-part-i
В нем используются некоторые функции Scala, такие как дженерики, обозначенные символами [S], которые похожи на интерфейсы Java, но более мощные,:: чтобы добавить наблюдателя в список наблюдателей и использовать foreach с параметром, используя _, который оценивается текущим наблюдателем.
Ответ 4
Вы можете использовать scala.collection.mutable.Publisher и scala.collection.mutable.Subscriber для создания pub/sub-реализации