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",了解简单性如何帮助你构建更好的软件。

相关推荐
心前阳光3 小时前
Unity发布PC软件图标不能改变
unity·游戏引擎
an869500110 小时前
unity如何在visual studio中打断点debug
unity·游戏引擎·visual studio
xcLeigh11 小时前
Unity基础:使用Transform控制物体移动——Translate与position详解
unity·游戏引擎
cjp56011 小时前
012.UG二次开发,UG管道服务器与WPF管道通讯,传输JSON数据
c#
FairGuard手游加固12 小时前
Unity小游戏加密:global-metadata.dat与AssetBundle保护
游戏·unity·游戏引擎
jiushidt12 小时前
ArcGIS Pro Add‑in 打包流程详解
arcgis·c#·.net·arcgispro
善良勤劳勇敢而又聪明的老杨13 小时前
【AI编程系列】MCP 常用设计模式解读
设计模式·ai编程
真鬼12314 小时前
【Unity AI】Untiy链接cursor与MCP
unity·游戏引擎
WarPigs15 小时前
Unity设置人物位置无效的原因
unity
geovindu15 小时前
java: Strategy Pattern
java·开发语言·后端·设计模式·策略模式·行为模式