这在实现多个接口时,是否仍遵循了依赖反转原则?

huangapple go评论88阅读模式
英文:

Is this still follow Dependency Inversion Principle when implement multiple interface?

问题

抱歉,代码部分不做翻译。以下是翻译好的内容:

抱歉,问题有点长,而且我的英语也不太好。

我在阅读有关依赖倒置原则的文章。我将在这里对代码进行总结。

他们创建了两种不同的CoffeeMachine。BasicCoffeeMachine和PremiumCoffeeMachine。它们都有一个相同的特性,即brewFilterCoffee(),因此将它放在CoffeeMachine接口中。

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

// 这个可以制作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();
    }
}

在Main类中。

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

        app.prepareCoffee();
    }
}

我感到困惑的地方是,他们没有说明如何在CoffeeApp中使用brewEspressoCoffee()。所以我继续修改了CoffeeApp,像这样:

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

在Main类中,如果我想要brewEspressoCoffee(),我只需创建一个实现了EspressoMachine的实例。

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

        app.prepareEspressoCoffee(premiumCoffeeMachine);
    }
}

这还是遵循依赖倒置原则吗?有没有比这个示例更好的方法?如果有示例会更加赞赏。

谢谢!

英文:

sorry for the long question and also my English.

I'm reading an article about DIP. I will summarize the code in here.

interface CoffeeMachine() {
    void brewFilterCoffee();
}

interface EspressoMachine() {
    void brewEspressoCoffee();
}

They create two different CoffeeMachine. BasicCoffeeMachine and PremiumCoffeeMachine. They both have the same feature is brewFilterCoffee(); so they put it on the CoffeeMachine interface

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...");
    }
}

When they create CoffeeApp, it accepts CoffeeMachine interface in the constructor and uses it to prepareCoffee()

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

In the Main class.

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

        app.brewFilterCoffee();
    }
} 

I left confused here because they didn't mention how they use brewEspressoCoffee() in CoffeeApp.
So I go ahead and modify CoffeeApp like this:

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

In the Main class, if I want to brewEspressoCoffee(), I just create an instance that implements EspressoMachine

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

        app.brewEspressoCoffee(premiumCoffeeMachine);
    }
} 

Is this still the following DIP? And is there any better way to approach rather than this example? Any example would be appreciated.

Thank you!!

答案1

得分: 0

我认为你已经捕捉到了DIP的精髓,即你总是可以插入一个接口来反转依赖的方向。

除了遵循DIP之外,在这里还有要考虑的"信息隐藏"原则。我们通常认为IH适用于数据,但它也适用于依赖关系。

在原始的CoffeeApp中,客户端(顾客)不依赖于EspressoMachine,而间接(传递性)依赖于CoffeeMachine。在修改后的CoffeeApp中,客户端直接依赖于两个Machine接口。

这些依赖关系是对抽象的依赖,所以DIP得到了满足;但这引出了一个问题,如果CoffeeApp向其客户端公开其依赖关系,那么它的目的是什么?客户端可以直接调用这些依赖关系。通过传递其依赖关系,CoffeeApp变得无用。

英文:

I think you've captured the essence of the DIP, which is that you can always insert an interface to invert the direction of a dependency.

Beyond just following the DIP, there is also the principle of Information Hiding to consider here. We often think of IH as applied to data, but it applies to dependencies as well.

In the original CoffeeApp, the client (customer) has no dependency on EspressoMachine and an indirect (transitive) dependency on CoffeeMachine. In the modified CoffeeApp, the client has direct dependencies on both Machine interfaces.

These dependencies are on abstractions, so the DIP is satisfied; but it begs the question, if CoffeeApp exposes its dependencies to its clients, then what is its purpose? Clients can invoke those dependencies directly. By passing on its dependencies, the CoffeeApp becomes useless.

huangapple
  • 本文由 发表于 2020年10月7日 15:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/64239688.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定