我最近开始学习Scala并开始了一个小项目来创建一个简单的roguelike游戏。但是,我坚持尝试实现观察者模式。 This回答了这个主题,但我无法弄清楚如何让它发挥作用。以下是上面链接的答案中的代码。我对代码的“ this:S => ”部分感到困惑,我想我应该有一些函数,但我不确定。我想让它从类中返回一个元组,它将扩展Subject特征。
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))
}
答案 0 :(得分:9)
请参阅Steve关于self
类型和其他代码示例的答案。
以下是使用观察者的一些示例代码。 ObservedAccount
是Subject
观察者观察到的AccountReporter
。
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))
}
class Account(initialBalance: Double) {
private var currentBalance = initialBalance
def balance = currentBalance
def deposit(amount: Double) = currentBalance += amount
def withdraw(amount: Double) = currentBalance -= amount
}
class ObservedAccount(initialBalance: Double) extends Account(initialBalance) with Subject[Account] {
override def deposit(amount: Double) = {
super.deposit(amount)
notifyObservers()
}
override def withdraw(amount: Double) = {
super.withdraw(amount)
notifyObservers()
}
}
class AccountReporter extends Observer[Account] {
def receiveUpdate(account: Account) =
println("Observed balance change: "+account.balance)
}
让我们看看它的实际效果:
scala> val oa = new ObservedAccount(100.0)
oa: ObservedAccount = ObservedAccount@3f947e20
scala> val ar = new AccountReporter
ar: AccountReporter = AccountReporter@6ea70a98
scala> oa.addObserver(ar)
scala> oa.deposit(40.0)
Observed balance change: 140.0
scala> oa.withdraw(40.0)
Observed balance change: 100.0
答案 1 :(得分:3)
以Brian的回答为基础:我发现没有必要设置单独的Observer[S]
特征,只需S => Unit
就足够了:
trait Subject[S] {
this: S =>
private var observers: List[S => Unit] = Nil
def addObserver(observer: S => Unit) = observers = observer :: observers
def notifyObservers() = observers.foreach(_.apply(this))
}
class Account(initialBalance: Double) {
private var currentBalance = initialBalance
def balance = currentBalance
def deposit(amount: Double) = currentBalance += amount
def withdraw(amount: Double) = currentBalance -= amount
}
class ObservedAccount(initialBalance: Double) extends Account(initialBalance)
with Subject[Account] {
override def deposit(amount: Double) = {
super.deposit(amount)
notifyObservers()
}
override def withdraw(amount: Double) = {
super.withdraw(amount)
notifyObservers()
}
}
class AccountReporter {
def receiveUpdate(account: Account) =
println("Observed balance change: " + account.balance)
}
object Main extends App {
println("start app")
val oa = new ObservedAccount(100.0)
val ar = new AccountReporter
oa.addObserver(ar.receiveUpdate _)
oa.deposit(40.0)
oa.deposit(60.0)
println("stop app")
}
/**
a copy paste observer pattern scala mini-app
sbt run should produce:
[info] Running app.Main
start app
Observed balance change: 140.0
Observed balance change: 200.0
stop app
*/
答案 2 :(得分:2)
很抱歉回答问题。您是否已阅读your answer here或the more interesting answer here和here?有人应该编制阅读清单,如果他们没有。 Coursera有阅读清单吗?
答案 3 :(得分:1)
这是一个Scala自我类型(参见http://www.scala-lang.org/node/124)。它表达了一个要求,即特质主题[S]的所有具体实现也必须符合类型S.也就是说,每个可观察的主体[S]本身就是一个S.
这对于Observer模式是合理的 - 它是可观察主题本身应该具有注册和通知方法,因此与S的观察者一致的主体本身应该是S。