Skip to content

Instantly share code, notes, and snippets.

@marnix
Created March 2, 2012 06:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save marnix/1956213 to your computer and use it in GitHub Desktop.
Save marnix/1956213 to your computer and use it in GitHub Desktop.
This code is a copy (roughly reconstructed from reformatted and reordered parts in an abandoned Eclipse project) of the code that was originally in http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html#comment-7789930.
trait BeeperDevice {
def beep(beepSound: String)
}
trait DependsOnBeeper {
protected val beeper: BeeperDevice
}
class Beeper extends BeeperDevice {
def beep(beepSound: String) = println("beep: " + beepSound)
}
// =======================
// An aspect that can be mixed in with any TriggeredDevice. It also just
// extends the DependsOn interface instead of using self-typing.
trait BeepWhenTriggeredAspectDependencies extends DependsOnBeeper {
trait BeepWhenTriggeredAspect extends TriggeredDevice {
abstract override def trigger = {
beeper.beep(name + " triggered")
super.trigger
}
}
}
class EmergencyShutoffSwitch extends TriggeredDevice {
protected val name = "emergency switch"
def trigger = {
println("EMERGENCY SHUTOFF")
}
}
class Heater extends OnOffDevice {
def on = println("heater.on")
def off = println("heater.off")
}
trait OnOffDevice {
def on: Unit
def off: Unit
}
trait DependsOnOnOffDevice {
protected val onOff: OnOffDevice
}
class PotSensor extends SensorDevice {
def isCoffeePresent = true
}
trait SensorDevice {
def isCoffeePresent: Boolean
}
trait DependsOnSensorDevice {
protected val sensor: SensorDevice
}
// =======================
// instantiate the services in a module
object ServiceRegistry extends WarmerDependencies with BeepWhenTriggeredAspectDependencies {
// onOff and sensor are required by the compiler because ServiceRegistry
// extends WarmerDependencies. They are injected into warmer. They are
// protected, because, in this example, ServiceRegistry consumers don't
// need to know about them
protected val onOff = new Heater
protected val sensor = new PotSensor
// beeper is required by the compiler because ServiceRegistry mixes in
// BeepWhenTriggeredAspectDependencies. It is injected into warmer
// and emergencySwitch. It is public so ComponentyRegistry consumers can
// us it
val beeper = new Beeper
// A warmer that beeps when it's triggered
val warmer = new Warmer with BeepWhenTriggeredAspect
// An emergency shutdown switch that beeps when it's triggered
val emergencySwitch = new EmergencyShutoffSwitch with BeepWhenTriggeredAspect
}
// =======================
// instantiate the services in a module
object ServiceRegistrySimple extends WarmerDependencies {
// onOff and sensor are required by the compiler because ServiceRegistry
// extends WarmerDependencies. They are injected into warmer. They are
// protected, because, in this example, ServiceRegistry consumers don't
// need to know about them
protected val onOff = new Heater
protected val sensor = new PotSensor
// A warmer that beeps when it's triggered
val warmer = new Warmer
}
trait TriggeredDevice {
protected val name: String
def trigger
}
//TODO: add 'DependsOn...' for consistency
// =======================
// Service declaring two dependencies that it wants injected. It just extends
// and mixes in the DependsOn interfaces instead of using self-typing, so that
// users of WarmerDependencies aren't required to explicitly mix in the
// DependsOn interfaces
trait WarmerDependencies extends DependsOnOnOffDevice with DependsOnSensorDevice {
class Warmer extends TriggeredDevice {
protected val name = "warmer"
def trigger = {
if (sensor.isCoffeePresent) onOff.on
else onOff.off
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment