4

对不起,我在软件工程上交叉发帖,不知道它被不赞成。

对于那些好奇的人,我得到的答案正是我想要的:https ://softwareengineering.stackexchange.com/a/347143/269571


原始问题

我正在阅读Robert C. Martin《敏捷软件开发、原则、模式和实践》一书。

当他谈到依赖倒置原则时,他给出了以下 DIP 违规示例:

DIP 违规

这对我来说似乎很清楚,因为高级对象Button依赖于低级对象Lamp

他带来的解决方案是:

解决方案

他创建了一个接口,这样Button就不再依赖于对象了Lamp

这个理论对我来说似乎很清楚,但是我无法在现实生活中的项目中使用这个原理。

  • 谁来SwitchableDevice确定需要调用哪些类(实现)?

  • 告诉Button他需要打开/关闭哪些设备?

  • 你如何告诉一个使用抽象事物的对象它需要使用哪些具体事物?(如果这个问题完全错误,请纠正我)

如果我的问题有任何不清楚的地方,请告诉我,我很乐意为您澄清。

4

2 回答 2

3

依赖注入的全部意义(至少按照我的理解)是Button不需要知道SwitchableDevice它正在切换的具体内容。

抽象接口可能如下所示:

struct SwitchableDevice {
    virtual void switchOn() = 0;
    virtual void switchOff() = 0;
};

按钮可以这样实现:

struct Button {
    SwitchableDevice& dev;
    bool state = false;
    Button(SwitchableDevice& d) : dev(d) {}
    void buttonPress(){
        if (state) { dev.switchOff(); }
        else       { dev.switchOn();  }
        state = !state;
    }
};

对于按钮,就是这样!没有人需要告诉按钮 的具体实现是什么SwitchableDevice,换句话说:Button和的实现SwitchableDevice是解耦的。

a 的可能实现Lamp如下所示:

struct Lamp : SwitchableDevice {
    void switchOn(){std::cout << "shine bright" << std::endl;}
    void switchOff(){std::cout << "i am not afraid of the dark" << std::endl;}
};

可以这样使用:

int main(){
    Lamp lamp;
    Button button(lamp);
    button.buttonPress();
    button.buttonPress();
}

希望有帮助...

好处是现在我们可以单独更改 theButton和 the的实现Lamp,而无需更改另一部分的任何内容。例如 aButtonForManyDevices可能看起来像这样:

struct ButtonForManyDevices {
    std::vector<SwitchableDevice*> devs;
    bool state = false;
    Button(std::vector<SwitchableDevice*> d) : devs(d) {}
    void buttonPress(){
        if (state) for (auto d: devs) { d.switchOff(); }
        else       for (auto d: devs) { d.switchOn();  }
        state = !state;
    }
};

同样,您可以完全更改 的行为Lamp(当然,在SwitchableDevice不必更改按钮上的任何内容的范围内。ButtonForManyDevices甚至可以使用相同的方法来切换 a Lamp、 aVaccumCleaner和 a MicroWaveOven

于 2017-04-13T18:00:43.000 回答
0

他是说按钮控制的东西应该比灯更通用。如果您为按钮可以控制的每种类型的事物都有按钮类,那么您可能会得到很多按钮类。

在第一个示例中,描述了灯上的按钮。它本质上是以灯为起点,将其划分为组件。

在第二个示例中,他正在划分部分并更一般地查看按钮。

谁来确定需要调用哪些类(实现 SwitchableDevice)?

按钮和界面之间必须有一个链接。

谁告诉 Button 他需要打开/关闭哪些设备?

Button 类需要实现一种机制来告诉它连接到什么设备。

你如何告诉一个使用抽象事物的对象它需要使用哪些具体事物?(如果这个问题完全错误,请纠正我)。

因为从抽象接口派生的对象必须完全实现该接口。Lamp 对象必须在某处定义 TurnOn 和 TurnOff 方法。

于 2017-04-13T17:58:04.217 回答