5.Unity面向对象-依赖倒置原则

依赖倒置原则(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的其余部分一样,依赖倒置原则要求你检查你通常如何设置类之间的关系。通过松耦合方便地扩展你的项目。

相关推荐
小程故事多_802 小时前
从基础Agent到复杂工作流,LangGraph如何用状态机重构智能体开发
人工智能·设计模式·重构·aigc·ai编程
hypoy2 小时前
Claude Code 的 1M Context 怎么用:一篇官方文章的读后整理
设计模式·claude
mxwin4 小时前
Unity URP 下 UI 特效开发指南 深入探索顶点色、Mask 交互与扭曲特效的实战技巧
ui·unity·游戏引擎·shader
CandyU25 小时前
Unity入门
unity·游戏引擎
IT 行者5 小时前
软件设计模式会不会是制约大模型编程的障碍?
设计模式·ai编程
t***5445 小时前
还有哪些设计模式适合现代C++
开发语言·c++·设计模式
t***5445 小时前
如何在现代C++项目中有效应用这些设计模式
开发语言·c++·设计模式
呆呆敲代码的小Y6 小时前
48个AI智能体搭建完整游戏开发工作室:Claude Code Game Studios
人工智能·游戏·unity·ai·游戏引擎·ai编程·ai游戏
贵慜_Derek6 小时前
我们能从 DeerFlow 学到哪些优秀的技术架构设计
人工智能·设计模式·架构
Q741_1476 小时前
设计模式之装饰器模式 理论总结 C++代码实战
c++·设计模式·装饰器模式