依赖注入(DI)是否鼓励或遵循单一职责原则(SRP)?
依赖注入如何促进单一职责原则(SRP)
你说得没错——依赖的合理使用是SRP的核心,但DI的价值在于它会强制/引导你划清职责边界,而手动实例化依赖很容易让类悄悄承担额外职责却不自知。下面用具体例子对比说明:
反例:手动实例化依赖,违反SRP
假设我们有一个处理订单的类:
public class OrderService { private readonly SqlConnection _dbConnection; private readonly FileLogger _logger; public OrderService() { // 手动初始化数据库连接,要处理连接字符串、超时配置 _dbConnection = new SqlConnection("Server=...;Database=..."); _dbConnection.Open(); // 手动初始化日志类,要处理日志路径、级别 _logger = new FileLogger(@"C:\logs\orders.log", LogLevel.Info); } public void CreateOrder(Order order) { // 核心业务:保存订单到数据库 var command = _dbConnection.CreateCommand(); command.CommandText = "INSERT INTO Orders (...) VALUES (...)"; // ...执行逻辑 // 记录日志 _logger.Log($"Created order {order.Id}"); } }
这个OrderService现在承担了三个职责:
- 处理订单业务逻辑(本该是它唯一的职责)
- 初始化并管理数据库连接的生命周期
- 初始化并配置日志组件
手动创建依赖时,很自然就把“依赖创建”的职责塞进了业务类里,不知不觉就违反了SRP——这个类不再只专注于订单业务,还要操心数据库和日志的初始化细节。
正例:构造函数注入DI,遵循SRP
用DI重构后,我们先定义依赖的抽象:
public interface IDbConnectionFactory { IDbConnection CreateConnection(); } public interface ILogger { void Log(string message); }
然后OrderService只依赖抽象,通过构造函数注入:
public class OrderService { private readonly IDbConnectionFactory _dbConnectionFactory; private readonly ILogger _logger; // 依赖通过构造函数注入,类不再负责创建依赖 public OrderService(IDbConnectionFactory dbConnectionFactory, ILogger logger) { _dbConnectionFactory = dbConnectionFactory; _logger = logger; } public void CreateOrder(Order order) { // 核心业务:只处理订单逻辑,依赖的创建交给外部 using var connection = _dbConnectionFactory.CreateConnection(); var command = connection.CreateCommand(); command.CommandText = "INSERT INTO Orders (...) VALUES (...)"; // ...执行逻辑 _logger.Log($"Created order {order.Id}"); } }
现在OrderService的职责只有一个:处理订单业务逻辑。数据库连接的创建、日志组件的初始化,这些职责都被剥离到专门的IDbConnectionFactory实现类和ILogger实现类里,每个类都只做自己的事。
DI促进SRP的关键原因
- 强制职责分离:DI容器要求你把依赖的创建逻辑从业务类中抽离,你没办法在业务类里偷偷初始化依赖(除非刻意违规),这从结构上就避免了职责膨胀。
- 依赖抽象而非具体:DI鼓励面向接口编程,业务类只关心依赖提供的能力,不关心具体实现,这让类更专注于自身业务,不会被依赖的实现细节干扰。
- 降低修改扩散:如果数据库连接需要改配置,或者日志要换成Elasticsearch实现,只需要修改对应的工厂/日志类,
OrderService完全不用动——这正是SRP要达到的目标:修改一个职责,不会影响其他职责。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

