设计模式之美08--接口隔离原则

客户端不应该被强迫依赖它不需要的接口。其中的“客户端”,可以理解为接口的调用者或者使用者。

  1. 如何理解“接口隔离原则”?

理解“接口隔离原则”的重点是理解其中的“接口”二字。这里有三种不同的理解。
如果把“接口”理解为一组接口集合,可以是某个微服务的接口,也可以是某个类库的接口等。如果部分接口只被部分调用者使用,我们就需
要将这部分接口隔离出来,单独给这部分调用者使用,而不强迫其他调用者也依赖这部分不会被用到的接口。
如果把“接口”理解为单个API接口或函数,部分调用者只需要函数中的部分功能,那我们就需要把函数拆分成粒度更细的多个函数,让调用
者只依赖它需要的那个细粒度函数。
如果把“接口”理解为OOP中的接口,也可以理解为面向对象编程语言中的接口语法。那接口的设计要尽量单一,不要让接口的实现类和调用
者,依赖不需要的接口函数。

  1. 接口隔离原则与单一职责原则的区别

单一职责原则针对的是模块、类、接口的设计。接口隔离原则相对于单一职责原则,一方面更侧重于接口的设计,另一方面它的思考角度也是
不同的。接口隔离原则提供了一种判断接口的职责是否单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。

把“接口”理解为一组API接口集合
现在,我们的后台管理系统要实现删除用户的功能,希望用户系统提供一个删除用户的接口。我只需要在UserService中新添加一个deleteUserByCellphone()接口就可以了。这个方法可以解决问题,但
是也隐藏了一些安全隐患。删除用户是一个非常慎重的操作,我们只希望通过后台管理系统来执行,所以这个接口只限于给后台管理系统使用。如果我们把它放到UserService中,那所有使用到UserService的系统,都可以调用这个接口。不加限制地被其他业务系统调用,就有可能导致误删用户。
当然,最好的解决方案是从架构设计的层面,通过接口鉴权的方式来限制接口的调用。不过,如果暂时没有鉴权框架来支持,我们还可以从代码设计的层面,尽量避免接口被误用。我们参照接口隔离原则,调用者不应该强迫依赖它不需要的接口,将删除接口单独放到另外一个接口
RestrictedUserService中,然后将RestrictedUserService只打包提供给后台管理系统来使用。

把“接口”理解为OOP中的接口概念
比如有3个配置项, dbConfig, kafkaConfig, redisConfig. 现在需要对dbConfig,redisConfig做热更新操作, 对kafkaConfig,dbConfig监控展示。我们设计应该是如下

public interface Updater {
	void update();
}
public interface Viewer {
	String outputInPlainText();
	Map<String, String> output();
}

public dbConfig implements Updater ,Viewer {......}

public kafkaConfig implements  Viewer {......}

public redisConfig implements  Updater {......}

错误示例; 如果我们不遵守接口隔离原则,不设计Updater和Viewer两个小接口,而是设计一个大而全的Config接口

public interface Config {
	void update();
	String outputInPlainText();
	Map<String, String> output();
} 
public class RedisConfig implements Config {
//...需要实现Config的三个接口update/outputIn.../output
}
public class KafkaConfig implements Config {
//...需要实现Config的三个接口update/outputIn.../output
} 
public class MysqlConfig implements Config {
//...需要实现Config的三个接口update/outputIn.../output
}

首先,第一种设计思路更加灵活、易扩展、易复用。因为Updater、Viewer职责更加单一,单一就意味了通用、复用性好。
比如,我们现在又有一个新的需求,开发一个Metrics性能统计模块,并且希望将Metrics也通过SimpleHttpServer显示在网页上,以方便查看。这个时候,尽管Metrics跟RedisConfig等没有任何关系。但我们仍然可以让Metrics类实现非常通用的Viewer接口。

其次,第二种设计思路在代码实现上做了一些无用功。因为Config接口中包含两类不相关的接口,一类是update(),一类是output()和outputInPlainText()。理论上,KafkaConfig只需要实现viewer()接口,并不需要实现output()相关的接口。同理,redisConfig只需要实现
Updater()相关接口,并需要实现output()接口。但第二种设计思路要求RedisConfig、KafkaConfig、MySqlConfig必须同时实现Config的所有接口函数(update、output、outputInPlainText)。除此之外,如果我们要往Config中继续添加一个新的接口,那所有的实现类都要改动。相反,如果我们的接口粒度比较小,那涉及改动的类就比较少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值