实现观察者模式

Zav*_*ior 3 scala

我最近开始学习Scala并开始了一个小项目来创建一个简单的roguelike游戏.但是,我坚持尝试实现观察者模式. 这个答案触及了这个主题,但我无法弄清楚如何使其发挥作用.以下是上面链接的答案中的代码.我对代码中的" 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))
}
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 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)
}
Run Code Online (Sandbox Code Playgroud)

让我们看看它的实际效果:

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
Run Code Online (Sandbox Code Playgroud)