做程序开发一段时间之后,会慢慢意识到面向过程编程与面向对象编程之间的差异。两种方式,都可以解决具体的问题,只是,面向过程编程无法应对复杂而多变的需求,随着项目不停迭代,复杂度上升,你会逐渐意识到它的短板以及灾难性的维护成本,这还只是其一;第二个会遇到的难题,就是用面向过程的编码方式,无法将简单的小功能堆砌为复杂而灵活的大功能,太多不必要的代码裸露出来,分散了你的注意力,无法将心思放在实现逻辑之上。如果不锻炼你的面向对象编程思维,你无法提高你的编码技术,犹如武侠中练武之人,不注重内功心法,学再多的武功秘籍,也无法将武技发挥到极致,更无法持久的输出战力。在面向对象编程中,有很多规定来约束对象的创建,以及接口的使用。约束对象创建方面,有里氏代换原则(遵循里氏代换原则可以让你将多态发挥到极致)以及开闭原则(对修改关闭,对扩展开放);接口使用方面,有依赖倒转原则(针对接口编程)以及接口隔离原则(保持接口职能单一)。
这篇文章中,本人分享一些自己的心得体会,强调定义接口的重要性,侧重点在于如何让接口见名知意,是如何定义接口的一个片段而已,并不囊括全部如何定义接口全部的内容。直接切入正题。
只处理抽象对象的情形
这个抽象基类定义了一些基本的属性值,强调的是取值的特性,行为特征少(方法很少或者没有方法)。而某些取值的差异化,是通过派生子类的方式重载对应属性的getter,setter方法而已,比方说,我们需要在子类中对取name值加一个前缀,那么,子类重载了其name属性的getter方法即可,接口的定义就用抽象基类输入参数为主:
只处理抽象接口的情形
这是一个协议,我们注重的是协议中通用的行为,任何对象,只要实现了这个行为,都可以作为接口的参数,那么,我们需要用下面的定义方式,来强调,你需要一个实现了此协议的对象:
对抽象对象与抽象接口都有要求的情形
如下所示,我们可以将抽象的接口附着在抽象的基类上,强调了这个抽象基类需要实现这些抽象的行为才能达到客户端的需要:
为了达到强调的效果,接口需要这么定义:
* 以上三个都是为了强调接口的可读性,让人知道你想表达什么,以及让使用者如何操作
万能适配的情形
你很有自信适配所有类型的数据,你会这么写:
这么写其实并不好,因为没人知道id类型的model到底是做什么用的,因为你没有对model进行任何行为的规范(没有指明model的类型,或者model需要遵守的协议),只有当你的接口适配了所有的对象,或者内部写好了适配器,才能这么做,即使是这样,也会让可读性变差。
以上讲的几点,都是基于抽象基类与抽象行为彼此分离的这种设定,抽象基类本身也会带有方法,只有在某些方法需要子类重载的时候,我们才会将其提取出来放在抽象行为(协议)当中,我们做这些事情的目的,核心思想都是在增加程序可读性以及可维护性。还有,代码是写给别人看的。