1.Unity面向对象-单一职责原则

单一职责原则

一个类应该只有一个更改理由,即只有单一职责。

SOLID原则中最重要的第一条是单一职责原则(SRP),它指出每个模块、类或函数负责一件事,并仅封装该部分逻辑。

用许多较小的组件组装你的项目,而不是构建庞大的类。更短的类和方法更容易解释、理解和实现。

如果你用Unity工作了一段时间,你可能已经熟悉这个概念。当你创建一个GameObject时,它包含各种较小的组件。例如,它可能包含:

  • 一个MeshFilter,存储对3D模型的引用
  • 一个Renderer,控制模型表面在屏幕上的显示方式
  • 一个Transform组件,存储缩放、旋转和位置
  • 一个Rigidbody,如果需要与物理模拟交互

每个组件只做一件事,而且做得很好。你整个场景都是用GameObject构建的。它们组件之间的交互使得游戏成为可能。

你将以相同的方式构建脚本组件。设计它们,使每个组件都能被清楚地理解。然后让它们协同工作,形成复杂的行为。

如果你忽略单一职责,你可能会创建这样一个自定义组件:

一个具有多重职责的Player脚本

复制代码
public class UnrefactoredPlayer : MonoBehaviour
{
    [SerializeField] private string inputAxisName;
    [SerializeField] private float positionMultiplier;
    private float yPosition;
    private AudioSource bounceSfx;
    
    private void Start()
    {
        bounceSfx = GetComponent<AudioSource>();
    }
    
    private void Update()
    {
        float delta = Input.GetAxis(inputAxisName) * Time.deltaTime;
        yPosition = Mathf.Clamp(yPosition + delta, -1, 1);
        transform.position = new Vector3(transform.position.x, yPosition * positionMultiplier, transform.position.z);
    }
    
    private void OnTriggerEnter(Collider other)
    {
        bounceSfx.Play();
    }
}

这个UnrefactoredPlayer类混合了多种职责。它在玩家与某物碰撞时播放声音,管理输入,并处理移动。即使这个类目前相对较短,随着项目的发展,维护起来也会变得棘手。考虑将Player类拆分成更小的类。

重构后的Player类,具有单一职责

复制代码
[RequireComponent(typeof(PlayerAudio), typeof(PlayerInput), typeof(PlayerMovement))]
public class Player : MonoBehaviour
{
    [SerializeField] private PlayerAudio playerAudio;
    [SerializeField] private PlayerInput playerInput;
    [SerializeField] private PlayerMovement playerMovement;
    
    private void Start()
    {
        playerAudio = GetComponent<PlayerAudio>();
        playerInput = GetComponent<PlayerInput>();
        playerMovement = GetComponent<PlayerMovement>();
    }
}

public class PlayerAudio : MonoBehaviour { ... }
public class PlayerInput : MonoBehaviour { ... }
public class PlayerMovement : MonoBehaviour { ... }

Player脚本仍然可以管理其他脚本组件,但每个类只做一件事。这种设计使代码更易于修改,特别是随着项目需求的变化。

另一方面,你需要将单一职责原则与常识保持平衡。不要过度简化到极端,创建只有一种方法的类。

在处理单一职责原则时,牢记这些目标:

  • 可读性:短类更容易阅读。没有硬性规定,但许多开发者将限制设为200-300行。自行或作为团队决定什么是"短"。超过这个阈值时,决定是否可以将其重构为更小的部分。
  • 可扩展性:你更容易继承小类。修改或替换它们而不必担心破坏意外的功能。
  • 可重用性:将你的类设计得小而模块化,这样你就可以将它们重用到游戏的其他部分。

进行重构时,需考虑代码重排如何提升自身或团队成员的工作效率与体验。

刚开始时多花些功夫,日后就能省去不少麻烦。

简单并不容易

简单性在软件设计中经常被讨论,是可靠性的前提。你的软件设计能处理生产中的变化吗?你能随着时间的推移扩展和维护你的应用程序吗?

本指南中介绍的许多设计模式和原则都帮助你实施简单性。这样做,它们使你的代码更可扩展、更灵活和更具可读性。但是,它们需要一些额外的工作和规划。"简单"不等于"容易"。

虽然你可以不使用这些模式创建相同的功能(而且通常更快),但快速和容易并不一定能导致简单。简单意味着专注。设计它做一件事,不要用其他任务使它复杂化。

请查看Rich Hickey的讲座"Simple Made Easy",了解简单性如何帮助你构建更好的软件。

相关推荐
WarrenMondeville2 小时前
2.Unity面向对象- 开闭原则
unity·游戏引擎·开闭原则
bmseven2 小时前
23种设计模式 - 适配器模式(Adapter)
设计模式·适配器模式
呆呆敲代码的小Y2 小时前
UnityMCP+Claude+VSCode,构建最强AI游戏开发环境
人工智能·vscode·游戏·unity·游戏引擎·u3d·mcp
C蔡博士2 小时前
Unity TextMeshPro 中文本地化:动态生成最小字体集(解决边缘模糊、乱码问题)
unity·游戏引擎
m0_630182462 小时前
Unity TMP 中文字体生成
unity·游戏引擎
寒风暖哥4 小时前
Oracle视图查询返回空数据集的分析
oracle·c#
万兴丶4 小时前
Unity用C#完成抖音小游戏接入引力引擎(Gravity Engine)完整指南,一篇文章讲清楚!
unity·c#·游戏引擎·抖音
MarkHD4 小时前
RPA工程化实践:三种核心设计模式让复杂流程优雅可控
linux·设计模式·rpa
AI大法师5 小时前
字标Logo设计指南:中文品牌如何用字体做出高级感与辨识度
人工智能·设计模式