在this博客文章中,这个动机海报描述了依赖性倒置原则:
我不明白海报的含义:如何将灯直接焊接到墙上违反了依赖性倒置原则,以及插头如何遵循依赖倒置原则。也许一些关于灯具和电源插座的骨架Java或C#代码可能会有所帮助。
答案 0 :(得分:3)
从您的链接:
SOLID中的“D”表示依赖性倒置原则 高级模块不应该依赖于低级模块,但是 两者都应该依赖于共享的抽象。
我不知道他们的意思是'共享'抽象。在代码中,灯将是“高级模块”,它所获得的功能将是它的依赖性,或者是“低级模块”。
您的问题:
如何将灯直接焊接到墙上违反了依赖性反转原理
海报中的灯违反了依赖性倒置原则,因为它不依赖于抽象电源。它依赖于直接焊接到墙壁中的电线的非常具体的实施方式。如果这种关系在代码中建模,它可能看起来像这样:
public class Lamp {
// This part is the equivalent of "soldering a lamp directly to the electrical wiring in a wall"
private ElectricalWiringInBobsWall electricalWiring = new ElectricalWiringInBobsWall();
private boolean isOn;
public void turnOn() {
electricalWiring.useElectricityInWatts(60);
isOn = true;
}
public void turnOff() {
electricalWiring.turnOffElectricityInWatts(60);
isOn = false;
}
}
这样做的后果是灯在其他情况下很难使用。在现实生活中,如果您想将灯移动到房子的不同部分,在发电机上使用,或者甚至将其带到海外并将其插入不同的插座,灯本身就需要进行大量的返工。同样地,在代码库中,如果你想用不同的电源重复使用这个灯,你必须改变灯本身的代码,这可能需要重新测试,或引入新的错误。
插头如何遵循依赖倒置原则
插座更抽象,因为作为用户,你真的不必知道灯泡是如何获得它的力量的。所有你必须知道的是,如果你插入灯,它的工作原理。插座是对电源的抽象。也就是说,它隐藏了权力实际来自何处的细节。墙壁,发电机,海外适配器,太阳能电池板电源等可能有插座。
在我们上面的类中使用DIP,我们希望Lamp
依赖于抽象,并将实现作为依赖项传递。在代码中,这可能如下所示:
public interface Outlet {
void useElectricityInWatts(int watts);
void turnOffElectricityInWatts(int watts);
}
public class Lamp {
private Outlet outlet;
private boolean isOn;
// We pass in the dependency instead of instantiating it and rely on an interface (abstraction)
public void plugInto(Outlet outlet) {
this.outlet = outlet;
}
public void turnOn() {
outlet.useElectricityInWatts(60);
isOn = true;
}
public void turnOff() {
outlet.turnOffElectricityInWatts(60);
isOn = false;
}
}
现在,一盏灯可以使用任何类型的插座:BobsOutletInHisWall,GeneratorOutlet,EuropeanAdapterOutlet等。它可以在其他情况下轻松移动和使用,而不必改变。
我知道这个例子远非完美,但我希望这能解释海报的含义。
答案 1 :(得分:0)
这类似于不硬编码的常见做法,例如您的控制器(控制流程的类),模型(数据来源)。
例如,这会很糟糕,不可测试或很容易“不可插拔”:
public function index()
{
return $some->sql()->logic()->where('this', '=', 'that');
}
相反,您会将存储库注入控制器:
public function __construct(Somerepo $repo)
{
$this->repo = $repo;
}
然后,您可以通过repo中的方法继续访问所需的SQL语句。
public function index()
{
return $this->repo->getStuff();
}
这样,您可以轻松更改或“拔出”数据的来源,而无需触及控制器逻辑。