As part of the Scala Study Group in Albuquerque, we had an assignment to reproduce some of the popular design patterns in Scala. Although the assignment is over, it is worth while to log about it. The following pattern was taken from Groovy Decorator Example.
trait Logger { def log(message: String) = { message } }
Figure 1: Establishing a trait shared by all Loggers.
object StdLogger extends Logger
Figure 2: Objects are explicit creations of an object. There are no statics in Scala, and for good reason. Reasons that are too many for me to cover here. What this does is create an object called StdLogger. This is merely an implementation of the trait with no added behavior.
class TimeStampingLogger(logger: Logger) extends Logger { override def log(message: String) = { val now = Calendar.getInstance now.getTime.toString + ' ' + logger.log(message) } }
Figure 3: The time stamping logger takes a Logger object and decorates with the current time prepended with whatever message is returned from the parent logger.
class UpperLogger(logger: Logger) extends Logger { override def log(message: String) = { logger.log(message).toUpperCase } }
Figure 4: The UpperLogger will capitalize all letters returned from the parent Logger object.
object DecoratorRunner extends Application { override def main(args: Array[String]) { val timeStampingLogger = new TimeStampingLogger(StdLogger) val upperLogger = new UpperLogger(timeStampingLogger) println(upperLogger.log(StdLogger.log("Decorator for the Scala Study Group"))) } }
Figure 5: The application runner itself. I instantiate the TimeStampingLogger and the UpperLogger. Note that I do not instantiate the StdLogger because that already is instantiated because it is an object. I chain them together and produce the needed result.