Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Scala's cake pattern to implement robot legs?

My development makes extensive use of the robot legs binding problem. I know how to solve it with PrivateModule in Guice, but it isn't clear how this would be done with Scala's cake pattern.

Could someone explain how this would be done, ideally with a concrete example based off of Jonas Boner's coffee example at the end of his blog post? Maybe with a warmer that could be configured for left and right sides, injected with an orientation and a def isRightSide?

like image 611
Jeff Axelrod Avatar asked Jan 27 '12 14:01

Jeff Axelrod


1 Answers

Cake pattern doesn't solve this problem in its original form. You have several choices how to deal with that. The solution I prefer is to create each "robot leg" by calling its constructor with appropriate parameter - code shows that better, than words.

I think the answer cited above is more readable, but if you are already familiar with Jonas' example, here is how you'd make Warmer configurable with an orientation:

// =======================
// service interfaces
trait OnOffDeviceComponent {
  val onOff: OnOffDevice
  trait OnOffDevice {
    def on: Unit
    def off: Unit
  }
}
trait SensorDeviceComponent {
  val sensor: SensorDevice
  trait SensorDevice {
    def isCoffeePresent: Boolean
  }
}

// =======================
// service implementations
trait OnOffDeviceComponentImpl extends OnOffDeviceComponent {
  class Heater extends OnOffDevice {
    def on = println("heater.on")
    def off = println("heater.off")
  }
}
trait SensorDeviceComponentImpl extends SensorDeviceComponent {
  class PotSensor extends SensorDevice {
    def isCoffeePresent = true
  }
}
// =======================
// service declaring two dependencies that it wants injected
trait WarmerComponentImpl {
  this: SensorDeviceComponent with OnOffDeviceComponent =>

  // Note: Warmer's orientation is injected by constructor.
  // In the original Cake some mixed-in val/def would be used
  class Warmer(rightSide: Boolean) {
    def isRightSide = rightSide
    def trigger = {
      if (sensor.isCoffeePresent) onOff.on
      else onOff.off
    }
  }
}

// =======================
// instantiate the services in a module
object ComponentRegistry extends
  OnOffDeviceComponentImpl with
  SensorDeviceComponentImpl with
  WarmerComponentImpl {

  val onOff = new Heater
  val sensor = new PotSensor
  // Note: now we need to parametrize each particular Warmer
  // with its desired orientation
  val leftWarmer = new Warmer(rightSide = false)
  val rightWarmer = new Warmer(rightSide = true)
}

// =======================
val leftWarmer = ComponentRegistry.leftWarmer
leftWarmer.trigger
like image 109
Przemek Pokrywka Avatar answered Nov 15 '22 03:11

Przemek Pokrywka