2012-06-30 14 views
22

Niedawno zobaczyłem rozmowy Dead-Simple Dependency Injection i Dependency Injection Without the Gymnastics o DI z Monadami i byłem pod wrażeniem. Próbowałem zastosować go do prostego problemu, ale nie udało mi się, gdy tylko stało się to nie banalne. Naprawdę chciałbym zobaczyć uruchomioną wersję wstrzykiwania zależności gdzieUżywanie czytnika Reader do iniekcji zależności

  • klasa, która zależy od więcej niż jedną wartość, która ma być wstrzykiwany
  • klasę, która zależy od klasy, która jest uzależniona od czegoś być wstrzykiwany

jak w poniższym przykładzie

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() 

byłoby bardzo pomocne, aby zobaczyć przykładową implementację przy użyciu czytnika monada odkąd tylko opłaty l, że brakuje mi pchnięcia we właściwym kierunku.

Dzięki!

Odpowiedz

26

"Monada czytelnika" to tylko Function1, więc wystarczy zaakceptować argument zawierający wszystkie potrzebne rzeczy. Na przykład:

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

type Env[A] = Config => A 

Teraz, jeśli chcemy skonstruować Duck na podstawie tego środowiska:

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

A potem konstruowania Zoo oparciu o które jest łatwe:

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

Korzystanie Scalaz (lub z odrobiną pracy na własną rękę) możesz użyć kilku składni niceties, aby "zapytać" o konfigurację c:

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

Dzięki za twój przykład. Ciekawi mnie, czy ty (lub wiesz o jakichś większych projektach) używasz tego zamiast wiosennej lub goolge Guice dla DI? Czy jest to lepsze według twojego doświadczenia? –

+2

Tak, używamy tego w znacznym stopniu i jest o wiele bardziej pożądane. Jeśli kiedykolwiek zobaczę wiosnę lub Guice, to będzie za wcześnie. – Apocalisp

+0

@Apocalisp, czy możesz pomóc mi zastosować to rozwiązanie do http://stackoverflow.com/questions/12341867/how-to-avoid-dependency-injection-in-scala/12363015#12363015? –

Powiązane problemy