You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

游戏引擎开发中Singleton与传递Application引用方案对比及命名咨询

方案优劣对比

单例方案

  • 优势
    • 无需逐层传递引用,深层组件可直接调用Application::getInstance()获取实例,编码成本极低
    • 无需修改现有类的构造函数签名,改造成本极低
  • 劣势
    • 强绑定全局状态,完全无法做单元测试,不能Mock Application实例验证组件逻辑
    • 依赖隐式化,仅看组件代码无法感知到它对Application的依赖,问题排查成本极高
    • 后续扩展性极差,如果要做多实例编辑器、多窗口并行运行等功能,单例完全不支持
    • 生命周期不可控,程序退出时销毁顺序容易出问题,大概率会出现野指针访问崩溃

手动传递+继承基类方案

  • 优势
    • 依赖完全显式,所有需要访问Application的类都有明确的继承标记,依赖关系一目了然
    • 无全局状态,单元测试可传入自定义的Application实例,支持多实例场景扩展
    • 生命周期可控,只要保证所有持有引用的组件在Application销毁前释放,就不会出现野引用
    • 减少重复代码,无需每个需要访问Application的类单独声明引用成员、编写初始化逻辑
  • 劣势
    • 初期改造成本高,深层组件需要Application引用时,要修改所有上层节点的构造函数传参
    • 引入了继承关系,如果组件类已有其他父类,会带来C++多继承的额外复杂度
    • 所有继承类都和Application强耦合,后续如果要拆分Application的功能模块,所有相关类都要调整

其他可行方案

服务定位器模式

实现一个轻量的全局服务容器,将Application拆分出的子模块(输入、渲染、日志等)注册到容器中,组件仅按需获取对应的服务实例,不需要依赖完整的Application。

  • 优势:比直接用单例灵活,支持替换服务实现,耦合度远低于依赖完整Application
  • 劣势:仍存在全局状态,依赖还是隐式的,问题排查成本高于显式传参

细粒度依赖传递

不传递完整的Application引用,组件需要什么能力就传对应模块的引用,比如需要输入就传InputSystem&,需要日志就传Logger&。

  • 优势:耦合度最低,每个类仅依赖自己需要的接口,单元测试成本最低
  • 劣势:需要提前拆分Application的各个功能模块,初期开发工作量大

纯显式依赖注入

不使用公共基类,每个需要依赖的类自行在构造函数中声明需要的参数,由上层创建实例时传入。

  • 优势:无继承负担,不会引入多继承问题
  • 劣势:每个类都要重复写引用声明、初始化逻辑,重复代码多

基类命名建议

如果确定使用该基类方案,最符合业内开发规范的命名是ApplicationAware。Aware后缀是通用命名惯例,明确表示该类的子类「可以感知、访问Application实例」,语义清晰且符合多数开发框架的命名习惯。
如果你的项目风格更偏向直白命名,也可以选择ApplicationReferenceHolder,但长度更长,通用性不如前者。


内容的提问来源于stack exchange,提问作者user3621272

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:36:08