Dieser Artikel ist der Artikel zum 9. Tag von Just a Group Adventskalender 2019.
Es gibt so viele Artikel im Internet, dass ich selten über DI-Container spreche. (~~ Angeltitel ~~)
In diesem Artikel wird der Zweck des DI-Containers,
Ich werde über mm sprechen
Wenn es keinen DI-Container auf der Welt gibt und Sie manuell tun müssen, was der DI-Container tut, schreiben wir den Code tatsächlich, um zu sehen, welche Art von Implementierung möglich ist.
Ein Framework, das Anwendungen mit DI-Funktionen (Dependency Injection) versorgt.
Einzelheiten finden Sie in den folgenden Artikeln.
Was ist ein DI-Container DI / DI-Container, verstehst du richtig ...? -Qiita
Warum brauchen Sie DI überhaupt? Die sehr wichtigen Zwecke von DI sind wie folgt.
Dies kann auch als Interessentrennung bezeichnet werden.
In SOLID ist es das Prinzip der Abhängigkeitsumkehr.
DI ist ein Weg, um diese Ziele zu erreichen.
Neben DI gibt es verschiedene Möglichkeiten, dies zu erreichen.
In diesem Artikel werde ich einige der verschiedenen Möglichkeiten vorstellen, um die oben genannten Ziele in der Codebasis zu erreichen.
Wenn ich die Suchmethode teste, wird tatsächlich eine JobRepositoryImpleWithMysql-Instanz erstellt Wenn JobRepositoryImpleWithMysql mit DB verknüpft ist, ist das Testen sehr schwierig.
class SearchUseCase {
def search = {
val repositoryImpleWithMysql = new JobRepositoryImpleWithMysql
...........
}
}
Wenn Sie JobRepositoryImpleWithMysql in jobRepositoryImpleWithElasticSearch ändern, Die Benutzerseite (SearchUseCase) muss ebenfalls Korrekturen vornehmen.
class SearchUseCase {
def search = {
val repositoryImpleWithMysql = new JobRepositoryImpleWithMysql
...........
}
}
class JobRepositoryImpleWithMysql {
def getJobs: Seq[String] = Seq("job1", "job2")
}
Es gibt drei Hauptmuster. In diesem Artikel werde ich diejenigen in Fettdruck mit dem eigentlichen Code vorstellen.
Da ** Kuchenmuster ** und ** abstraktes Fabrikmuster ** auch "Umkehrung der Kontrolle" realisieren, werden wir uns zunächst nur ** Konstruktormuster ** ansehen.
Das Kuchenmuster scheint ein Muster zu sein, das Scala eigen ist. (Referenz)
package study.ConstractPattern
class Main {
def main(args: Array[String]): Unit = {
val useCase = new SearchUseCase(new JobRepositoryImpleWithMysql)
useCase.search
}
}
class SearchUseCase(jobRepositoryImpleWithMysql: JobRepositoryImpleWithMysql) {
//JobRepositoryImple wird im Konstruktorargument an SearchUseCase delegiert.
//Anstatt Objekte mit neuem JobRepositoryImple ohne searchUseCase zu injizieren
//Durch Injizieren, von wo aus das SearchUseCase-Objekt deklariert wird
//Die Abhängigkeitsinjektion kann von außen durchgeführt werden.
//Sie können dies von außen nutzen! Einspritzen eines Objekts.
val jobRepositoryImpleInstance = jobRepositoryImpleWithMysql
def search: Seq[String] = {
jobRepositoryImpleInstance.getJobs
}
}
trait JobRepository {
def getJobs: Seq[String]
}
class JobRepositoryImpleWithMysql extends JobRepository {
override def getJobs: Seq[String] = Seq("job1", "job2")
}
class jobRepositoryImpleWithElasticSearch extends JobRepository {
override def getJobs: Seq[String] = Seq("job1", "job2")
}
Wie ich im Kommentar geschrieben habe, kann ich die Erstellung und Verwendung des Objekts trennen, indem ich das Objekt einfüge, das als Konstruktorargument verwendet werden soll.
―― Am Ende müssen Sie zum Zeitpunkt der Anwendungsausführung ein neues Objekt erstellen, damit sich Ihre Verantwortlichkeiten dort konzentrieren.
Beispiel: Wenn jobRepositoryImpleWithMysql in jobRepositoryImpleWithElasticSearch geändert wird, müssen Sie einige Änderungen vornehmen.
Es gibt die folgenden Methoden.
abstract factory pattern
package study.abstractFactoryPattern
class Main {
def main(args: Array[String]): Unit = {
val searchUseCase = new SearchUseCase
searchUseCase.search
}
}
//Der Benutzer muss die konkrete Klasse nicht kennen.
//Steuern Sie die Erstellung von Objekten auf der Anwendungsseite
class SearchUseCase {
def search = {
val repository: JobRepository = JobRepositoryFactory.createJobRepository
repository.getJobs
}
}
// abstract factory
trait AbstractFactory {
def createJobRepository: JobRepository
}
// abstract product
trait JobRepository {
def getJobs: Seq[String]
}
// concrete factory
object JobRepositoryFactory extends AbstractFactory {
override def createJobRepository: JobRepository = new JobRepositoryImple
}
// concrete product
class JobRepositoryImple extends JobRepository {
override def getJobs: Seq[String] = Seq("job1", "job2")
}
cake pattern
package study.cakePattern
class Main {
def main(args: Array[String]): Unit = {
//Injizieren von searchUseCase selbst
val useCase = ComponentRegistry.searchUseCase
useCase.search
}
}
//Abstrakte Komponente
//Schließen Sie es in Komponenten ein und erstellen Sie für jeden einen Namespace
trait JobRepositoryComponent {
val jobRepository: JobRepository
trait JobRepository {
def search: Unit
}
}
//Betonbauteile
//Schließen Sie es in Komponenten ein und erstellen Sie für jeden einen Namespace
trait JobRepositoryComponentImple extends JobRepositoryComponent {
class JobRepositoryImple extends JobRepository {
override def search: Unit = println("create user")
}
}
//Client-Komponenten
//Deklarieren Sie Abhängigkeiten von UserRepository mithilfe von Annotationen vom Typ Self
trait SearchUseCaseComponent { self: JobRepositoryComponent =>
class SearchUseCase {
def search = {
//Ich möchte, dass dieses JobRepository injiziert wird
self.jobRepository.search
}
}
}
//Injektor (Rolle des DI-Containers)
//SearchUseCaseComponent deklariert JobRepositoryComponent mit einer eigenen Typanmerkung
//JobRepositoryComponentImple muss ebenfalls eingemischt werden
object ComponentRegistry extends SearchUseCaseComponent with JobRepositoryComponentImple {
override val jobRepository = new JobRepositoryImple
val searchUseCase = new SearchUseCase
}
Bei der Suchmethode der SearchUseCase-Klasse wird die Steuerungsumkehr realisiert, indem auf die abstrakte Klasse (JobRepository) zurückgegriffen wird, anstatt von der konkreten Klasse (JobRepositoryImple) abhängig zu sein.
Wir haben verschiedene Wege gesehen, wie oben beschrieben. Durch die Verwendung des DI-Containers wurde mir die Bequemlichkeit des DI-Containers bewusst, da er intern eine komplizierte Verarbeitung durchführt.
Gibt es Nachteile bei der Einführung eines DI-Containers?
Danke bis zum Ende mm
[Abhängigkeitsinjektion-Wikipedia](https://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6%80%A7%E3%81%AE%E6%B3% A8% E5% 85% A5)
Denken: Entwurfsmuster (abstraktes Fabrikmuster) - Qiita
Scala im aktuellen Kampf: Abhängigkeitsinjektion mit Kuchenmuster (DI) | eed3si9n
[DI (Cake Pattern Introduction) mit Scala | TECHSCORE BLOG](https://www.techscore.com/blog/2012/03/27/scala%E3%81%A7di-%EF%BC%88cake-pattern% E5% B0% 8E% E5% 85% A5% E7% B7% A8% EF% BC% 89 /)
Recommended Posts