抽象工厂本身不直接实现服务容器注入,而是封装一组相关对象的创建逻辑;它需与DI容器协同:将抽象工厂接口注册为服务,由容器注入其依赖并管理生命周期,工厂再通过IServiceProvider按需解析具体产品,确保产品族一致性与运行时可切换性。

抽象工厂本身不直接实现“服务容器注入”,它是一种创建型设计模式,核心职责是**封装一组相关对象的创建逻辑**。所谓“多类型服务容器注入”,其实是将抽象工厂与现代依赖注入(DI)容器(如 Spring、.NET Core DI、Autofac)结合使用后形成的一种架构实践——抽象工厂提供产品族的创建能力,而 DI 容器负责管理其生命周期、解析依赖并完成自动注入。
抽象工厂如何融入服务容器
DI 容器并不原生识别“抽象工厂”这个设计模式,但它能很好地支持其结构:
-
抽象工厂接口作为服务契约注册:例如
IUserRepositoryFactory或IDatabaseCommandFactory被注册为服务(Scoped/Singleton),而非具体实现类。 -
具体工厂由容器实例化并注入依赖:比如
SqlServerCommandFactory构造函数中需要ILogger或IConfiguration,容器会自动解析并传入。 -
工厂方法返回的对象可继续参与 DI 管理:若工厂创建的是带构造依赖的服务(如
SqlServerUserCommand依赖IDbConnection),需确保该对象本身也注册进容器,或由工厂内部用容器IServiceProvider解析(即“服务定位反模式”的谨慎变体)。
典型实现方式(以 .NET 为例)
在 Startup 或 Program.cs 中配置:
- 注册多个具体工厂实现,按条件或命名区分:
services.AddSingleton<IDatabaseFactory, SqlServerFactory>();services.AddSingleton<IDatabaseFactory, OracleFactory>(); - 通过工厂接口 + 策略模式组合:定义
IDatabaseFactoryProvider,根据连接字符串自动选择对应工厂,再注入到业务服务中。 - 避免硬编码 new:所有具体产品(如
SqlCommand,OleDbCommand)不直接 new,而是由工厂统一创建,保证产品族一致性。
为什么不是“自动注入所有产品类型”
抽象工厂不主张把每个具体产品(如 ModernButton、MacTextField)单独注册进容器——那样就退化为普通服务注册,失去了“成套切换”的意义。它的价值在于:
- 客户端只依赖
IUIFactory,调用CreateButton()和CreateTextField()即得风格一致的配套组件; - 切换 UI 风格只需替换工厂实现(如从
WindowsFactory改为MacFactory),无需改动任何使用方代码; - 容器只是帮工厂自身及其依赖被正确构造和传递,不替代工厂对产品族的编排逻辑。
关键注意事项
实际落地时容易踩的坑:
- 工厂类本身不应持有状态,保持无状态(stateless)才能安全复用;
- 若工厂创建的对象需 DI 支持(如带 Repository 依赖的 Service),推荐让工厂接收
IServiceProvider并按需解析,但要控制作用域,防止内存泄漏; - 不要用抽象工厂去替代策略模式或简单工厂——它专治“多产品族+强一致性”场景,不是万能对象创建器。

















