读懂 SOLID 的「接口隔离」原则

这是理解 SOLID原则,关于 接口隔离原则如何帮助咱们建立简单的抽象接口,并使客户端代与接口之间存在的更少的依赖关系。

接口隔离原则是什么

Clients should not be forced to depend on methods that they do not use.

客户端代码不该当被迫依赖于它们不须要的方法。架构

这个原则自己与单一职责原则关系十分紧密,它意味着当你在定义你的抽象层代码时,不该当在客户端代码在实现抽象逻辑时,暴露一些客户端代码不须要使用或者关心的方法。app

进一步说明的话,就是当你有意地在抽象层中暴露的方法时,这意味着全部实现这些抽象逻辑的客户端代码都必需要实现全部的抽象方法,尽管这些方法并不必定都对客户端代码有意义。函数

将你的接口的保持精简和小颗粒度,而且不要在它们中间增长无用的抽象方法,当你在对新的抽象接口进行命名时,你就会拥有更好的选择,由于你已有了若干小颗粒的命名类型。这样作的意义在于当你在须要提供一个更加大颗粒度的抽象接口时,你能够拥有足够的灵活性来将已有的小颗粒度接口进行组合。工具

如何实践接口隔离原则

这个例子是关于一个ATM用户界面的抽象接口,这个接口会处理诸如存款请求、取款请求等逻辑,从这个例子中咱们会了解到,咱们如何对这个接口进行隔离,使其进一步划分为多个独立的、更加具体的若干接口。优化

首先咱们应当有一个工具函数库接口,这个接口会描述咱们想要暴露的关于byte操做逻辑的方法,让咱们建立这样一个接口,以下spa

type ByteUtils interface {
    Read(b []byte) (n int, err error) // Read into buffer
    Write(b []byte)(n int, err error) // Write into buffer
    Trim(b []byte, exclusions string)[]byte // Trim buffer by removing bytes from the exclusion chars
}

它能够正常工做一段时间,可是很快咱们就会发现如下两个问题:设计

  • 它的命名ByteUtils太过于通用,若是咱们仅经过命名自己,基本没法获取任何具体的信息
  • 当使用它时,会有一些古怪的感受,由于当你根据不一样的优化场景来按不一样逻辑实现trim方法时,你所实现的readwrite几乎没什么差异,可是你却须要重复地实现它们,同时在某些不须要读或者写的场景,仍然须要实现它们。

因此它虽然可以正常工做,可是却不够好。code

咱们能够经过建立三个更精简、更具体的接口来替代原先通用的接口:接口

type Reader interface {
    Read(b []byte) (n int, err error) 
}
type Writer interface {
    Write(b []byte)(n int, err error) 
}
type Trimmer interface {
    Trim(b []byte, exclusions string)[]byte 
}

这种颗粒度比较细的接口也能够称为角色接口,由于它们更易于重构和改变,甚至对于已经定义好的角色和目的也能够很容易的进行从新部署和定义。ip

在这三个基础上,咱们能够经过组合它们来获取一个更有关联性的接口列表,好比:

type ReadWriter interface {
    Reader
    Writer 
}
type TrimReader interface {
    Trimmer
    Reader
}

这意味客户端代码拥有了能够根据它们各自的需求来组合抽象层接口的灵活性,这样就会避免在实现抽象接口时没必要要的麻烦(好比必需要实现某些无用的方法),好比上面的TrimReader的实现并未包含多余的Write方法的声明。

总结

正如你所看到的,通用的接口每每会无心识的将本身和类的实现耦合在了一块儿,因此你应当尽可能的避免这种状况的发生。在设计接口时,你应当时刻提醒本身,我是否须要使用全部在接口中声明的方法呢?若是不是的话,将接口细分为更多个更精简、更具体的接口。

正如甘地曾经说过:

你的行动决定你的习惯,你的习惯决定你的价值,你的价值会决定你的命运。

若是在架构中,你每次都会通过仔细思考,会按照好的模式来进行设计,它将会成为一种习惯,天然慢慢会转变为你的价值或者原则,最终则会成为你的命运,好比成为了一个始终给予完善解决方案的软件架构师。

个人观点是,始终经过挑战本身来变的更好,在某些时刻,你可能会遇到问题,可是每每你可能已经拥有了答案。

Happy coding!

译者注

对于接口隔离原则的理解,我一直觉的它自己实际上是单一职责原则的一个扩展,可是它们之间也有细微的不一样:

  • 单一职责原则每每面向实现层,好比具体的类或者某个方法
  • 接口隔离原则每每面向抽象层,好比一些抽象类或者抽象方法

因此将两个原则结合起来看的话,能够很容器获得当时提出这两个原则的人的意图,那就是必定要时刻保持简单

在实际工做中,我深知保持简单是一件十分困难的事情,由于工程师自己的使命即是解决问题,而问题每每充满了未知性,而未知性每每表明着改变,这尚未考虑到在项目实施过程当中,产品经理天马行空的设计思路,客户们五花八门的需求等等。在这些外界条件下,咱们的代码每每会变得复杂无比,充满了各类反模式和冗余代码,最终会使本身陷入无尽的bug修复和维护工做中,怎么还会有时间进行自我提高呢?

因此,为了可以按时下班,为了可以及早回家,为了可以让咱们的拥有更多的时间来提高本身和陪伴家人,在软件设计之初,尽量地针对未来所面临的改变,在设计层面下降软件抽象模块间的耦合程度,在项目实施时,提升每一个具体实现模块内部的内聚程度,同时使它们保持简单,这样即是一个好的开始。

关注公众号 全栈101,只谈技术,不谈人生

clipboard.png

相关文章
相关标签/搜索