为何提取接口后可替换底层实现?该问题是否属设计模式范畴?
1. 为什么添加接口后更易于区分和替换类调用?
拿单元测试的实际场景举例:
假设你写了个UserService类,它直接依赖MySQLDataStore来读写用户数据。现在要给UserService写单元测试,总不能每次测试都真的连数据库吧?
如果没接口,你得硬改UserService的代码,把MySQLDataStore换成测试用的假类,测完还要改回去,折腾得很。
但如果先定义一个IDataStore接口,只声明GetUserById()、SaveUser()这些核心方法,再让MySQLDataStore和MockDataStore(测试用的假实现)都实现这个接口。这时候UserService只依赖IDataStore,而非具体的MySQLDataStore——想换实现?直接把MockDataStore传进去就行,UserService的代码一行不用动。
从「区分」的角度看,接口本身就是个契约:不管是真实数据库实现还是Mock实现,只要实现了IDataStore,就肯定能完成数据读写的核心功能。看接口的方法名和参数,一眼就知道这个类该干哪些事,不用去抠具体实现的细节,不同实现的职责边界一下子就清晰了。
2. 这个问题是否属于设计模式范畴?
它更贴近SOLID设计原则里的依赖倒置原则(依赖抽象,而非具体类),但很多设计模式(比如策略模式、工厂模式)都是基于这个原则衍生出来的。接口是实现依赖倒置的常用手段,所以这个问题和设计模式/设计原则关系非常紧密,属于设计思想的范畴,而设计模式是这种思想的具体落地方式。
3. 是否需要学习设计模式来更好地理解此问题?
需要,但不用上来就死记硬背23种设计模式。你可以先从SOLID原则入手,尤其是依赖倒置原则,结合正在学的单元测试场景理解——为什么要依赖接口?就是为了测试时能轻松替换真实依赖。
等你理解了这些基础原则,再看相关的设计模式(比如策略模式就是用接口封装不同算法,和这里替换类调用的逻辑本质一致),会发现很多设计模式都是在解决「如何灵活替换组件」这类问题。学设计模式能帮你把这种做法从「为了测试而做」上升到「为了代码可维护性而做」的层面,不止是单元测试,平时写业务代码也能更得心应手。
内容的提问来源于stack exchange,提问作者bokabokaboka

