PHP中创建带依赖对象的最佳实践:RelevantClass实例化选型
PHP依赖注入方案选型:构造函数传参vs Setter注入
核心依赖区分
首先明确两个依赖的本质:
SomeServiceClass是稳定的无状态服务依赖,可复用、不随业务场景变化EntityClass是可变的有状态业务实体,需从数据库获取且会被修改,每次实例可能不同
方案1的问题
直接调用构造函数传入EntityClass,同时内部通过DI容器注入SomeServiceClass,存在明显缺陷:
- 紧耦合DI容器:
RelevantClass内部依赖容器获取服务,违反依赖注入的核心原则——业务类不应知晓容器存在,会大幅降低可测试性(测试时必须模拟容器而非直接传入SomeServiceClass实例)。 - 混淆依赖边界:构造函数同时接收初始化服务和运行时业务数据,模糊了类的职责,后续维护成本高(比如更换DI容器时需修改类内部逻辑)。
方案2的固有优势
通过DI容器实例化RelevantClass(注入SomeServiceClass)后,调用setEntity传入业务实体,更符合最佳实践:
- 遵循依赖倒置:
RelevantClass仅依赖SomeServiceClass的抽象(若为接口则更优),不耦合容器,测试时可直接Mock服务依赖,提升可测试性。 - 清晰边界划分:构造函数负责初始化稳定服务依赖,setter方法处理可变业务数据,类的职责单一,逻辑更清晰。
- 更高灵活性:后续更换
EntityClass的来源(如从缓存获取),只需修改调用setEntity的业务代码;若需用同一个RelevantClass实例处理多个实体,可多次调用setter方法。
补充最佳实践建议
如果RelevantClass必须持有EntityClass才能正常工作(无实体则无法执行核心逻辑),可以考虑让DI容器统一处理所有注入:
- 封装
EntityClass的获取逻辑为工厂类,由DI容器注入工厂到RelevantClass,在类内部通过工厂获取实体; - 或让DI容器负责从数据库获取
EntityClass实例,再注入到RelevantClass的构造函数中——绝对避免在业务代码中直接new RelevantClass。
内容的提问来源于stack exchange,提问作者David Drothler
相关产品推荐
相关产品推荐

