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

Python中向多个类传递同一对象实例的最优实现方案是什么?

结论先行

方案3是最符合Python开发规范、可维护性最好的选择,三个方案的具体优劣分析如下:

各方案问题分析

方案1(类属性绑定)存在的缺陷

  • 加载时机不可控:GameData实例会在States类第一次被导入时就触发初始化,如果GameData的初始化需要加载本地资源、依赖运行时的路径配置,导入阶段就执行加载非常容易触发路径不存在、配置未初始化的错误。
  • 耦合度过高:States类和GameData强绑定,后续如果需要替换GameData实现(比如单元测试时用Mock对象模拟资源),必须修改States类的源码,违反依赖倒置原则。
  • 扩展性差:如果后续需要新增其他状态类、或者需要多套GameData资源切换,全局绑定的类属性会带来大量交叉影响的问题。

方案2(子类分别实例化)存在的缺陷

你自己的判断是对的,这种方案完全没必要:GameData存储的是只读公共资源,实例化两次等于把图片、音效等资源重复加载两次,既浪费内存,又拖慢项目启动速度;如果后续GameData新增了可写的临时状态,两个实例数据不同步还会引发逻辑bug。

方案3(依赖注入)的优势

  • 完全符合依赖注入的设计原则,依赖对象从外部传入,类不需要自己硬编码创建依赖,耦合度极低。
  • 资源仅加载一次,多个状态类共用同一份只读资源,内存占用最优,也不存在数据不同步的问题。
  • 可测试性极强:单元测试时可以直接传入Mock的GameData对象,不需要真的加载大量资源就能测试状态类的逻辑。
  • 加载时机完全可控:可以等项目的路径、配置都初始化完成之后再实例化GameData,不会出现导入阶段意外触发加载的问题。

可选优化方案

可以把game_data的接收逻辑提到父类States中,减少子类的重复代码,同时用super()调用父类初始化方法更符合Python开发规范:

from game_data import GameData


class States:
    """Superclass for each state"""
    def __init__(self, game_data):
        self.done = False
        self.next = None
        self.quit = False
        self.previous = None
        # 父类统一存储game_data,子类不用重复实现
        self.game_data = game_data


class Game(States):
    def __init__(self, game_data):
        super().__init__(game_data)

    def some_method(self):
        pass # 直接通过self.game_data访问资源


class MainMenu(States):
    def __init__(self, game_data):
        super().__init__(game_data)

    def some_method(self):
        pass


game_data = GameData()
game = Game(game_data)
main_menu = MainMenu(game_data)

如果你的项目规模极小,不想每次传参,也可以给GameData实现单例模式,但单例的可测试性不如依赖注入,中大型项目优先选择方案3的依赖注入实现。


内容的提问来源于stack exchange,提问作者Miłosz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:27:04