单一职责原则
一个类应该只有一个更改理由,即只有单一职责。
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",了解简单性如何帮助你构建更好的软件。