Using Reader Monad for Dependency Injection

杀马特。学长 韩版系。学妹 提交于 2019-12-20 08:40:45

问题


I recently saw the talks Dead-Simple Dependency Injection and Dependency Injection Without the Gymnastics about DI with Monads and was impressed. I tried to apply it on a simple problem, but failed as soon as it got non-trivial. I really would like to see a running version of dependency injection where

  • a class that depends on more than one value that has to be injected
  • a class that depends on a class that depends on something to be injected

as in the following example

trait FlyBehaviour { def fly() }
trait QuackBehaviour { def quack() }
trait Animal { def makeSound() }

// needs two behaviours injected
class Duck(val flyBehaviour: FlyBehaviour, val quackBehaviour: QuackBehaviour) extends Animal 
{
   def quack() = quackBehaviour.quack()
   def fly() = flyBehaviour.fly()
   def makeSound() = quack()
}

// needs an Animal injected (e.g. a Duck)
class Zoo(val animal: Animal)

// Spring for example would be able to provide a Zoo instance
// assuming a Zoo in configured to get a Duck injected and
// a Duck is configured to get impl. of FlyBehaviour and QuackBehaviour injected
val zoo: Zoo = InjectionFramework.get("Zoo")
zoo.animal.makeSound()

It would be really helpful to see a sample implementation using the reader Monad since I just feel that I am missing a push in the right direction.

Thanks!


回答1:


The "reader monad" is just Function1, so all you need to do is accept an argument containing all the things you need. For example:

trait Config {
   def fly: FlyBehaviour
   def quack: QuackBehaviour
}

type Env[A] = Config => A

Now if you want to construct a Duck based on this environment:

val a: Env[Animal] = c => new Duck(c.fly, c.quack)

And then constructing a Zoo based on that is easy:

val z: Env[Zoo] = a andThen (new Zoo(_))

Using Scalaz (or with a bit of work on your own) you can make use of some syntax niceties to "ask" for the config c:

val z: Env[Zoo] = for {
  c <- ask
} yield new Zoo(Duck(c.fly, c.quack))


来源:https://stackoverflow.com/questions/11276319/using-reader-monad-for-dependency-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!