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
相关产品推荐
相关产品推荐

