接口隔离原则(Interface Segregation Principle)
接口隔离原则定义:客户端不应该被迫依赖于它不使用的方法
该原则还有另一个定义:一个类对另一个类的依赖应该建立在最小的接口上
通俗解释
要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用
接口隔离原则于单一职责原则的区别 接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者不同的:
- 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离
- 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架构建。
场景示例
用户系统提供了一组跟用户相关的 API 给其他系统 使用,比如:注册、登录、获取用户信息等。
struct UserInfo { }
protocol UserService {
func register(phoneNumber: String, password: String) -> Bool
func login(phoneNumber: String, password: String) -> Bool
func getUserInfoById(id: Int64) -> UserInfo
func getUserInfoByphoneNumber(phoneNumber: String) -> UserInfo
}
class UserServiceImpl: UserService { }
需求:管理系统要实现删除用户的功能,希望用户系统提供一个删除用户的接口,应该如何设计这个接口(假设这里我们不去考虑使用鉴权框架).
- 方案一:直接使用 UserService 接口添加一个删除用户接口
这个方法可以解决问题,但是也隐藏了一些安全隐患。删除用户是一个非常慎重的操作,我们只希望通过后台管理系统来执行,所以这个接口只限于给后台管理系统使用。如果我们把它放到 UserService 中,那所有使用到 UserService 的系统,都可以调用这个接口。不加限制地被其他业务系统调用,就有可能导致误删用户。
- 方案二:遵照接口隔离原则,为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。 将删除接口单独放到另外 一个接口 RestrictedUserService 中, 然后将 RestrictedUserService 只打包提供给后台管理系统来使用。
struct UserInfo { }
protocol UserService {
func register(phoneNumber: String, password: String) -> Bool
func login(phoneNumber: String, password: String) -> Bool
func getUserInfoById(id: Int64) -> UserInfo
func getUserInfoByphoneNumber(phoneNumber: String) -> UserInfo
}
protocol RestrictedUserService {
func deleteUserById(id: Int64) -> Bool
func deleteUserByPhoneNumber(phoneNumber: String) -> Bool
}
class UserServiceImpl: UserService & RestrictedUserService { }
遵循接口隔离原则的优势
- 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩展,提高系统的灵活性和可维护性。
- 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
- 能够减少项目工程的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余代码。