Sunday, October 10, 2010

Scala exercise 2: observer design pattern


This is the second exercise in my Scala exercises series. If you haven't seen it before, you may want to start from exercise 1: template method. Below is exercise 2: observer design pattern.

Problem: Complete a Scala trait Observed (shown below) to represent the subject being observed and the Scala trait Observer to represent an observer. The Observed object allows one or more Observers to register with it. Later, it can fire an event and notify all such Observers. The code is like (where E is the type of the event to be fired):

trait Observed[E] {
def addObserver(o: Observer[E]) ...
def notifyObservers(ev: E) ...

trait Observer[E] {
def eventOccurred(ev: E)

Then use these traits to implement Java bean "bounded properties", e.g., to allow others to get notified when properties of a Book instance is changed:

//Let others observe changes to its properties
case class Book(var title: String, var price: Double) extends Observed[PropertyChangeEvent] {
def setTitle(title: String) {
val oldTitle = this.title
this.title = title
//Notify the observers
def setPrice(price: Double) {
val oldPrice = this.price
this.price = price
//Notify the observers

//A sample observer class
class Foo extends Observer[PropertyChangeEvent] {
//Just print some info after a property has been changed
def eventOccurred(ev: PropertyChangeEvent) = {
printf("Foo: %s of %s has changed from %s to %s\n", ev.getPropertyName, ev.getSource, ev.getOldValue, ev.getNewValue)

object BeanTest {
def main(args: Array[String]) {
val b1 = new Book("Scala programming", 35.95)
val foo = new Foo
b1.addObserver(foo) //Register the observer
b1.setTitle("Thinking in Scala")  //foo should get an event
b1.setPrice(39.95) //ditto
b1.setTitle("Effective Scala") //ditto

The above code should print:
Foo: title of Book(Thinking in Scala,35.95) has changed from Scala programming to Thinking in Scala
Foo: price of Book(Thinking in Scala,39.95) has changed from 35.95 to 39.95
Foo: title of Book(Effective Scala,39.95) has changed from Thinking in Scala to Effective Scala

Try to do it now! Then, click here to see the answer.