Created
March 2, 2012 06:27
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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