Это все еще следует принципу инверсии зависимостей при реализации нескольких интерфейсов?

#java #solid-principles #dependency-inversion

#java #solid-принципы #зависимость-инверсия

Вопрос:

извините за длинный вопрос, а также за мой английский.

Я читаю статью о DIP. Я обобщу код здесь.

 interface CoffeeMachine() {
    void brewFilterCoffee();
}

interface EspressoMachine() {
    void brewEspressoCoffee();
}
  

Они создают две разные кофейные машины. BasicCoffeeMachine и PremiumCoffeeMachine. Они оба имеют одну и ту же функцию — brewFilterCoffee(); поэтому они помещают ее в интерфейс CoffeeMachine

 class BasicCoffeeMachine implements CoffeeMachine {
    @Override
    void brewFilterCoffee() {
        System.out.println("brewing filter coffee...");
    }
}

// this one can make Espresso
class PremiumCoffeeMachine implements CoffeeMachine, EspressoMachine {
    @Override
    void brewFilterCoffee() {
        System.out.println("brewing filter coffee but in premium way...");
    }

    @Override
    void brewEspressoCoffee() {
        System.out.println("brewing espresso coffee...");
    }
}
  

Когда они создают CoffeeApp, он принимает интерфейс CoffeeMachine в конструкторе и использует его для prepareCoffee ()

 class CoffeeApp {
    CoffeeMachine machine;
    
    public CoffeeApp(CoffeeMachine machine) {
        this.machine = machine;
    }
    
    public void prepareCoffee() {
        machine.brewFilterCoffee();
    }
}
  

В основном классе.

 class Main {
    public static void main(String[] args) {
        PremiumCoffeeMachine premiumCoffeeMachine = new PremiumCoffeeMachine();
        CoffeeApp app = new CoffeeApp(premiumCoffeeMachine);

        app.brewFilterCoffee();
    }
} 
  

Я оставил здесь в замешательстве, потому что они не упомянули, как они используют brewEspressoCoffee() в CoffeeApp.
Итак, я продолжаю и модифицирую CoffeeApp следующим образом:

 class CoffeeApp {
    public void prepareFilterCoffee(CoffeeMachine machine) {
        machine.brewFilterCoffee();
    }
    
    public void prepareEspressoCoffee(EspressoMachine machine) {
        machine.brewEspressoCoffee();
    }
}
  

В основном классе, если я хочу brewEspressoCoffee() , я просто создаю экземпляр, который реализует EspressoMachine

 class Main {
    public static void main(String[] args) {
        PremiumCoffeeMachine premiumCoffeeMachine = new PremiumCoffeeMachine();
        CoffeeApp app = new CoffeeApp();

        app.brewEspressoCoffee(premiumCoffeeMachine);
    }
} 
  

Это все еще следующий провал? И есть ли какой-нибудь лучший способ приблизиться, чем этот пример? Любой пример будет оценен.

Спасибо!!

Комментарии:

1. @Fildor не путайте DI (внедрение зависимостей) с DIP (принцип инверсии зависимостей), DIP говорит не о внедрении, а просто об использовании абстракции (например interface , like CoffeeMachine ) вместо фактической реализации (например BasicCoffeeMachine , )

2. Спасибо за ответ. @Lino Итак, я правильно следую DIP?

3. @ABC я бы так сказал, поскольку CoffeApp не зависит от реализации (т. Е. class ), А исключительно от абстракции (т. Е. interface )

4. @Lino, о котором я упоминал… «и с зависимостями от конкретных классов сверху» .

5. @Lino … но я был неправ. Перепутал интерфейсы для классов.

Ответ №1:

Я думаю, вы уловили суть DIP, которая заключается в том, что вы всегда можете вставить интерфейс, чтобы инвертировать направление зависимости.

Помимо простого следования за провалом, здесь также следует учитывать принцип сокрытия информации. Мы часто думаем о IH применительно к данным, но это относится и к зависимостям.

В оригинале CoffeeApp клиент (customer) не имеет зависимости от EspressoMachine и косвенной (транзитивной) зависимости от CoffeeMachine . В модифицированном CoffeeApp клиент имеет прямые зависимости от обоих машинных интерфейсов.

Эти зависимости основаны на абстракциях, поэтому провал удовлетворен; но возникает вопрос, если CoffeeApp он предоставляет свои зависимости своим клиентам, то какова его цель? Клиенты могут напрямую вызывать эти зависимости. Передавая его зависимости, CoffeeApp становится бесполезным.