为何在ServiceStation类中使用IGateUtility接口及构造函数注入?
关于单一职责原则(SRP)中接口依赖注入的疑问解答
兄弟,我懂你刚接触SOLID和接口注入时的困惑——这段代码里的接口看起来好像多此一举,但其实它是在帮你把代码写得更灵活、更符合单一职责原则,咱们一步步拆解来看:
为什么要在类里用接口?
核心原因是解耦+符合单一职责原则,具体好处有这几点:
- 各司其职,贴合SRP:
ServiceStation的核心职责是处理车辆服务逻辑(比如DoService里的校验和服务流程),而开关门、时间判断是完全独立的另一项职责。把这部分逻辑抽离到IGateUtility的实现类里,每个类只干一件事——以后如果要修改开门时间(比如从9点改成8点),你只需要改ServiceStationUtility的代码,完全不用碰ServiceStation,避免了牵一发而动全身。 - 灵活替换实现:如果以后你需要一个VIP服务站,开门时间是7点、关门是8点,你只需要新建一个
VIPGateUtility实现IGateUtility,然后把它传给ServiceStation就行,ServiceStation的代码一行都不用改。要是没有接口,你就得给ServiceStation加一堆判断逻辑,代码会越来越臃肿。 - 方便单元测试:写测试的时候,你不用依赖真实的时间判断(比如得等到9点才能测开门逻辑),可以写一个Mock的
IGateUtility实现,比如MockGateUtility,让OpenGate直接返回成功,这样就能单独测试ServiceStation的DoService逻辑,效率高多了。
关于IGateUtility _gateUtility;和构造函数的疑问
这是构造函数注入的写法,本质是让ServiceStation依赖抽象(接口)而不是具体实现:
IGateUtility _gateUtility;是在ServiceStation里声明一个接口类型的成员变量,意思是“我需要一个能完成开门关门功能的对象,但我不管它具体是谁”。- 构造函数
public ServiceStation(IGateUtility gateUtility)是告诉外部:“要创建我这个对象,必须给我传一个实现了IGateUtility的实例”。你需要传入的就是任何符合这个接口的类的对象,比如:
以后要换VIP门控,直接传新的实现就行:// 创建普通服务站的门控实例 var normalGate = new ServiceStationUtility(); // 把它传给ServiceStation var normalServiceStation = new ServiceStation(normalGate);var vipGate = new VIPGateUtility(); var vipServiceStation = new ServiceStation(vipGate);
简单来说,这种写法就是把“做什么”和“怎么做”分开——ServiceStation只知道要开门关门(做什么),具体怎么判断时间、怎么执行开关门(怎么做)交给实现接口的类来处理,这就是面向接口编程的核心思想,也是SOLID里依赖倒置原则(DIP)的体现哦。
内容的提问来源于stack exchange,提问作者Koosh
相关产品推荐
相关产品推荐

