工厂构造函数中智能指针的设计困境及解决方案咨询
工厂模式下的依赖生命周期管理问题
问题场景
当前使用工厂在运行时根据用户选择创建对象,代码如下:
class UpdateServiceFactory{ public: std::unique_ptr<UpdateService> create(Widget widget){ if(widget.name == "name one"){ auto dependency = std::make_unique<ChildDependency>(); return std::make_unique<ChildUpdateService>(std::move(dependency)); } } }
ChildUpdateService的构造有两种选择:
- a) 接收
std::unique_ptr<ChildDependency>:能实现UpdateService销毁时依赖自动释放,但强制创建者遵循单所有权策略,同一依赖无法复用给其他类; - b) 接收原始指针:可通过
unique_ptr::get()传递,但存在生命周期管理风险,工厂若承担生命周期管理则违反单一职责原则(SRP)。
咨询以下两个问题:
- 构造函数接收
unique_ptr是否不合理地强制了创建者的生命周期策略? - 是否有合适的设计模式解决该问题,比如用中间对象管理dependency的生命周期?
问题解答
1) 关于unique_ptr强制生命周期策略的合理性
构造函数接收unique_ptr确实会强制创建者遵循单所有权的生命周期策略。这种设计在依赖明确属于被创建服务独占的场景下是合理的,但如果存在依赖复用的需求,这种强制就会变成不必要的限制——因为unique_ptr的移动语义要求所有权完全转移,创建者在传递后就失去了对该依赖的控制权,无法再将其复用给其他对象。所以如果你的场景中存在依赖复用的可能,这种设计就是不合理的。
2) 可行的解决方案
针对这个问题,有几种符合设计原则的解决思路:
- 使用
std::shared_ptr管理依赖:将依赖的所有权改为共享模式,ChildUpdateService的构造函数接收std::shared_ptr<ChildDependency>。工厂创建依赖时用std::make_shared,传递给服务时无需移动,多个服务可以共享同一个依赖实例,生命周期由引用计数自动管理。这种方式既不用工厂额外承担生命周期管理,也解决了依赖复用的问题。 - 引入依赖注入(DI)容器:专门的DI容器负责所有依赖的生命周期管理(比如单例、请求作用域等),工厂只需要从容器中获取已创建的依赖实例,再组装成目标服务。这种方式严格遵循SRP——工厂仅负责对象的创建组装,容器负责依赖的生命周期,同时能灵活配置依赖的复用策略。
- 独立的生命周期管理器:创建一个
DependencyManager类,专门负责依赖的创建、存储和销毁。工厂从管理器中获取依赖的引用(或shared_ptr)来创建服务,完全不涉及生命周期管理逻辑,符合单一职责原则。管理器可以根据需求配置依赖的复用规则(比如单例、临时实例等)。
内容的提问来源于stack exchange,提问作者gfree
相关产品推荐
相关产品推荐

