Dependency injection - własna implementacja

0

Cześć!
Chciałem napisać własną implementację wzorca DI. Chciałbym się dowiedzieć, czy to co napisałem można wgl. nazwać dependency injection i dlaczego nie?

class Injector {
    private PrintFactory printFactory;
    private InputProvider inputProvider;
    private TextChecker textChecker;
    private FileHelper fileHelper;
    private LessonProvider lessonProvider;
    private KeyboardTeacher keyboardTeacher;

    private PrintFactory getPrintFactory() {
        if (printFactory == null)
            this.printFactory = new PrintFactory();
        return this.printFactory;
    }

    private InputProvider getInputProvider() {
        if ((inputProvider == null))
            inputProvider = new InputProvider();
        return inputProvider;
    }

    private TextChecker getTextChecker() {
        if(textChecker == null)
            textChecker = new TextChecker(
                    getInputProvider(),
                    getPrintFactory()
            );
        return textChecker;
    }

    private FileHelper getFileHelper() {
        if (fileHelper == null)
            fileHelper = new FileHelper(
                    getPrintFactory(),
                    getInputProvider()
            );
        return fileHelper;
    }

    private LessonProvider getLessonProvider() {
        if (lessonProvider == null)
            lessonProvider = new LessonProvider(
                    getPrintFactory(),
                    getInputProvider(),
                    getTextChecker(),
                    getFileHelper()
            );
        return lessonProvider;
    }

    KeyboardTeacher getKeyboardTeacher() {
        if (keyboardTeacher == null)
            keyboardTeacher = new KeyboardTeacher(
                    getPrintFactory(),
                    getFileHelper(),
                    getLessonProvider()
            );
        return keyboardTeacher;
    }
}

Wiem, że istnieje wiele bibliotek itd. ale chciałem zrozumiec jak to działa u podstaw. Klasa Injector właściwie powinna się nazywać Container lub coś podobnego, ale czy to w ogóle tak powinno działać? Jeśli potrafi mi ktoś to wyjaśnić, byłbym wdzięczny.
PS: Znacie jakąś dobrą książkę / stronę / jakiekolwiek źródło, dzięki któremu dobrze opanowałbym wzorce projektowe?

0

Jeśli lubisz materiały online zajrzyj tutaj:

https://refactoring.guru/design-patterns/java

Bardzo przejrzyście rozpisane wzorce, opis, przykładowy kod.

0

Mi ten twój kod wgl. nie wygląda na DI. Dobrym przykładem DI jest @Autowired na konstruktorze w Springu. Przez DI rozumiem - tworzę obiekt a wszelkie zależności przekazuje temu obiektowi przez konstruktor. Żadnego wywołąnia new wewnątrz instancji tego obiektu.

2

To co napisałeś to jest jakiś MotherOfAllSingletons albo od biedy ServiceLocator. Zauważ że nie ma tu żadnego odwróconego sterowania ani wstrzykiwania. Po prostu zrobiłeś sobie klasę która trzyma referencje do iluśtam innych obiektów. Ale tam gdzie chciałbyś ich używać i tak musiałbyś sam taki obiekt requestować, czyli siłą rzeczy NIE MA tam odwróconego sterowania ani wstrzykiwania zależności.

Dependency Injection jest związane z Dependency Inversion / Inversion of Control, czyli taką ideą że twój obiekt "dostaje" zależności a nie "sam je sobie zdobywa". Patrz:

Opcja klasyczna i to co napisałeś:

class A{
    private final B dependency;
    public A(){
        dependency = Injector.getB();
        // albo jakieś
        // dependency = new B();
    }
}

Widzisz że klasa A sama musi sobie zdobyć obiekt B.
Opcja DI:

class A{
    private final B dependency;
    public A(B injectedDependency){
        dependency = injectedDependency;
    }
}

Klasa A dostała zależność "skądś". Nie musi się o nią sama martwić.

2

Twój przykład jest taki dość abstrakcyjny. Zrób mniejszy, ale z testami, żeby było widać sens.

W zasadzie zrobiłes trochę więcej niż DI bo wstrzykujesz factory, ale może być.
Edit: żeby to miało sens to metody fabryczne muszą nie być private.

Jest dobry artykuł:
https://sites.google.com/site/unclebobconsultingllc/blogs-by-robert-martin/dependency-injection-inversion

Natomiast... powiem tak. NIe przejmyj się wzorcami i DI. Rób kod takm żeby był łatwo testowalny. Wtedy jakoś samo wyjdzie.

Z DI jest jak z prozą, trudno do końca zdefiniować. Jak patrzysz na pojedyncze zdanie to czasem nie wiadomo czy to proza. A do tego większość ludzi mówi prozą i o tym nie wie.
Co więcej, niektórzy, nieśmiali - potrzebują dodatkowych wspomagaczy - frameworków.
Ale nie trzeba. Twardym @Injection-om powiedz nie.

0

Dzięki wszystkim za odpowiedzi. Naprawdę bardzo mi pomogliście zrozumieć temat.

@kixe52 Czegoś takiego szukałem, dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1