面向对象的原则之接口隔离原则 谁践踏了优雅 2022-09-26 08:20 131阅读 0赞 # 接口隔离原则 # 设计应用程序的时候,如果一个模块包含多个子模块,那么我们应该小心对该模块做出抽象。设想该模块由一个类实现,我们可以把系统抽象成一个接口。但是要添加一个新的模块扩展程序时,如果要添加的模块只包含原系统中的一些子模块,那么系统就会强迫我们实现接口中的所有方法,并且还要编写一些哑方法。这样的接口被称为胖接口或者被污染的接口,使用这样的接口将会给系统引入一些不当的行为,这些不当的行为可能导致不正确的结果,也可能导致资源浪费。 ## 1.接口隔离 ## 接口隔离原则(Interface Segregation Principle,ISP)表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中的方法分组,然后用多个接口代替它,每个接口服务于一个子模块。简单地说,就是使用多个专门的接口比使用单个接口要好得多。 ISP的主要观点如下: 1)一个类对另外一个类的依赖性应当是建立在最小的接口上的。 ISP可以达到不强迫客户(接口的使用方)依赖于他们不用的方法,接口的实现类应该只呈现为单一职责的角色(遵守SRP原则)。 ISP还可以降低客户之间的相互影响——当某个客户程序要求提供新的职责(需求变化)而迫使接口发生改变时,影响到其他客户程序的可能性会最小。 2)客户端程序不应该依赖它不需要的接口方法(功能)。 客户端程序不应该依赖它不需要的接口方法(功能),那依赖什么?依赖它所需要的接口。客户端需要什么接口就提供什么接口,把不需要的接口剔除,这就要求对接口进行细化,保证其纯洁性。 比如在应用继承时,由于子类将继承父类中的所有可用的方法;而父类中的某些方法,在子类中可能并不需要。例如,普通员工和经理都继承自雇员这个接口,员工需要每天写工作日志,而经理则不需要。因此不能用工作日志来卡经理,也就是经理不应该依赖于提交工作日志这个方法。 可以看出,ISP和SRP在概念上是有一定交叉的。事实上,很多设计模式在概念上都有交叉,甚至你很难判断一段代码属于哪一种设计模式。 ISP强调的是接口对客户端的承诺越少越好,并且要做到专一。当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能性小。这实际上就是接口污染的问题。 ## 2.对接口的污染 ## 过于臃肿的接口设计是对接口的污染。所谓接口污染就是为接口添加不必要的职责,如果开发人员在接口中增加一个新功能的主要目的只是减少接口实现类的数目,则此设计将导致接口被不断地“污染”并“变胖”。 接口污染会给系统带来维护困难和重用性差等方面的问题。为了能够重用被污染的接口,接口的实现类就被迫要实现并维护不必要的功能方法。 “接口隔离”其实就是定制化服务设计的原则。使用接口的多重继承实现对不同的接口的组合,从而对外提供组合功能——达到“按需提供服务”。 看下面的例子 ![存在污染接口的设计][20160921133102424] 客户A需要A服务,只要针对客户A的方法发生改变,客户B和客户C就会受到影响。故这种设计需要对接口进行隔离。 ![接口隔离][20160921133238612] 在实际应用中,会遇到如下问题:比如,我需要一个能适配多种类型数据库的DAO实现,那么首先应实现一个数据库操作的接口,其中规定一些数据库操作的基本方法,如连接数据库、增删查改、关闭数据库等。这是一个最少功能的接口。对于一些MySQL中特有的而其他数据库不具有或性质不同的方法,如PHP里可能用到的MySQL的pconnect方法,其他数据库里并不存在和这个方法相同的概念,这个方法也就不应该出现在这个基本的接口里,那这个基本的接口应该有哪些基本的方法呢?PDO已经告诉你了。 PDO是一个抽象的数据接口层,它告诉我们一个基本的数据库操作接口应该实现哪些基本的方法。接口是一个高层次的抽象,所以接口里的方法应该是通用的、基本的、不易变化的。 还有一个问题,那些特有的方法应该怎么实现?根据ISP原则,这些方法可以在另一个接口中存在,让这个“异类”同时实现这两个接口。 对于接口的污染,可以考虑下面这两条处理方式: 利用委托分离接口。 利用多继承分离接口。 [20160921133102424]: /images/20220717/d143d546c1884fd5a39241a7de0ad67b.png [20160921133238612]: /images/20220717/d46e4578003941a68e097275bd0bd216.png
还没有评论,来说两句吧...