依赖倒置原则(DIP)指出高层模块不应该直接从低层模块导入任何东西。两者都应该依赖于抽象。
让我们解译这是什么意思。当一个类与另一个类有关系时,它有依赖或耦合。软件设计中的每个依赖都带有一些风险。
如果一个类对另一个类的工作方式了解太多,修改第一个类可能会损坏第二个类,反之亦然。高耦合被认为是不干净的代码实践。应用程序中一个地方的错误可能会滚雪球成很多。
理想情况下,目标是尽量减少类之间的依赖关系。每个类还需要其内部部分协同工作,而不是依赖外部连接。当你的对象基于内部或私有逻辑运行时,它被认为是内聚的。
在最佳情况下,目标是松耦合和高内聚。

你需要能够修改和扩展你的游戏应用程序。如果它是脆弱的并抵制修改,请调查它当前的结构方式。依赖倒置原则可以帮助减少类之间的紧密耦合。
在构建应用程序中的类时,有些自然"高级",有些"低级"。高级类依赖于低级类来完成某事。SOLID告诉我们切不要这样干。
假设你正在制作一个角色探索关卡并触发打开门的游戏。你可能想要创建一个名为Switch的类和另一个名为Door的类。

没有依赖倒置
Switch(高级)直接依赖于Door(低级)类。在高级层面,你希望角色移动到特定位置并发生某事。Switch将负责这一点。
在低级层面是另一个类Door,它包含如何打开门几何体的实际实现。为简化起见,添加了一个Debug.Log语句来表示开门和关门的逻辑。
public class Switch : MonoBehaviour
{
public Door door;
public bool isActivated;
public void Toggle()
{
if (isActivated)
{
isActivated = false;
door.Close();
}
else
{
isActivated = true;
door.Open();
}
}
}
public class Door : MonoBehaviour
{
public void Open()
{
Debug.Log("The door is open.");
}
public void Close()
{
Debug.Log("The door is closed.");
}
}
Switch可以调用Toggle方法来打开和关闭门。它有效,但问题是从Door直接向Switch连接了依赖。如果Switch的逻辑需要不仅仅适用于门,例如激活一盏灯或巨型机器人,该怎么办?
你可以在Switch类中添加额外的方法,但你违反了开闭原则。每次你想扩展功能时都必须修改原始代码。
再次是抽象来拯救。你可以在你的类之间插入一个名为ISwitchable的接口。
使用依赖倒置

两个类之间的接口ISwitchable
ISwitchable只需要一个公共属性,以便你知道它是否处于活动状态,再加上几个激活和停用它的方法。
public interface ISwitchable
{
public bool IsActive { get; }
public void Activate();
public void Deactivate();
}
然后Switch变成这样,依赖于ISwitchable客户端,而不是直接依赖于门。
public class Switch : MonoBehaviour
{
public ISwitchable client;
public void Toggle()
{
if (client.IsActive)
{
client.Deactivate();
}
else
{
client.Activate();
}
}
}
另一方面,你需要重构Door来实现ISwitchable:
public class Door : MonoBehaviour, ISwitchable
{
private bool isActive;
public bool IsActive => isActive;
public void Activate()
{
isActive = true;
Debug.Log("The door is open.");
}
public void Deactivate()
{
isActive = false;
Debug.Log("The door is closed.");
}
}
现在你倒置了依赖。接口在它们之间创建了一个抽象,而不是将开关硬连线到门。Switch不再直接依赖于门特定的方法(Open和Close)。相反,它使用ISwitchable的Activate和Deactivate。
这个小而重要的变化促进了可重用性。Switch以前只与Door一起工作,现在它与任何实现ISwitchable的东西一起工作。
这使你能够创建Switch可以激活的更多类。高级Switch将有效,无论是活板门还是激光束。它只需要一个实现ISwitchable的兼容客户端。

Switch现在可以激活任何ISwitchable对象。
与SOLID的其余部分一样,依赖倒置原则要求你检查你通常如何设置类之间的关系。通过松耦合方便地扩展你的项目。