转载自我一直关注的一位作者,原文链接如下:原文链接 。
大家好,欢迎来到公开课,今天公开课的内容是:面向接口编程思想。
有些东西,虽然人们对它理解的不透彻,但是人们仍然可以正确的使用,因为人们只要遵守它的规范,遵守它的语法就可以了。但是,想把它运用的更灵活,玩出花样,并且还想具备有一定的鉴赏力,那你必须吃透它背后的思想。而今天的公开课就是讲的背后的思想。
语法,你们都懂;用法,你们也懂,但是把它玩出花样,那就未必人人都可以做到的。
思想是有张力的,所以有的人写的代码很平淡,如同白开水一样;而有的人写的代码很拽,很惊艳。所以,有的时候,看起来思想这种东西很虚,其实它很有用的。所以,希望好好体会一下知识背后的思想。
上面都是题外话,我们开始进入正题。
首先我给大家解释一下“面向接口编程思想”,这八个字的含义,这八个字(面向接口编程思想)包含两层含义。第一层含义是面向接口,第二次含义是编程思想。
编程思想按照某种角度可以分为:面向对象编程,面向接口编程;按照另外某种角度,也可以划分为:面向业务编程,面向数据结构编程。今天我给大家介绍的是:面向接口编程思想。其他的内容今天不会涉及到。
接着,我给大家说一下Java语言的三大部分,每个部分背后对应一个思想:
(1)类部分,以class关键字定义,(我觉得,也应该包括注解部分),对应:面向对象编程思想。
(2)接口部分,以interface关键词定义,对应:面向接口编程思想
(3)基本类型部分,例如:char,int,long,数组等,对应:面向数据结构编程思想。
虽然Java是面向对象语言,但是因为它分为上面的几个部分,所以在Java中,不仅仅是面向对象编程思想,还有其他的编程思想。而大家往往忽略了这些了,所以我觉得有必要给大家讲讲面向接口编程思想。
面向接口编程思想,可以说是反面向对象编程思想的,它有很多地方与面向对象编程思想是相互独立,甚至是相对的。
接下来我给大家说一下,面向对象编程思想,对比一下面向接口编程思想。让大家体会一下这两者的区别。
第一点:在面向对象编程思想中,首先要定义一个类,这个类的要求是越详细越全面越好。
而在面向接口编程思想中,接口是越简单越精炼越好。你们看,这是不是与面向对象编程思想是相反的?我可以给大家举个例子来证明一下。
MyBatis框架就做到很好,接口设计的非常精炼。例如:SqlNode接口声明了1个方法;DataSourceFactory接口声明了2个方法;KeyGenerator接口声明了2个方法;WriteReplaceInterface接口声明了1个方法;ParameterHandler接口声明了1个方法;ResultSetHandler接口声明了1个方法SqlSource接口声明了1个方法;Command接口声明了1个方法;TokenHandler接口声明了1个方法;Interceptor接口声明了3个方法;ObjectFactory接口声明了3个方法;Transaction接口声明了4个方法;TransactionFactory接口声明了2个方法等等。
给大家举了这么多接口例子,只想说明一点,接口的设计越精炼越好。
第二点:在面向对象编程思想里面,暗含着自然界的生物法则:例如,一个类只能有一个父类。好比人一样,只有一个出生地,不可能有两个出生地。而接口就没有这种限制。你们看,这是不是与面向对象编程思想是相反的?
第三点:在面向对象编程思想中,最常用的两个操作是什么呢?一是定义一个父类,然后再继承这个类形成子类,这属于定义并继承操作。二是将不同的子类上溯成同一类型(也就是父类),这属于上溯操作。无论是定义并继承操作,还是上溯操作,都存在着自然界的物种观念,从父类子类这两个概念就可以提现出来,只要是存在相同的父类,那么任何子类都可以上溯成一类事物。而在面向接口编程思想中,抛弃了物种观念:
它不认属性,无论你是活生生的人,他是毫无生命可言的玩具,都无所谓;它只认功能,只要你和他有这个功能,不管你和他是否跨界,都可以当做一类事物。你们看,这是不是彻底与面向对象编程思想不一样了?
我发现编程中存在的问题:面向接口编程思想当外壳,核心还是面对对象编程思想。
就拿最近我做的一个优化功能,优化别人的代码。这是一个代理的功能。他定义了一个接口,名字叫:ProxyService,声明了32个方法,而实现这个接口的类只有一个ProxyServiceImpl。
对外都是以接口的形式被人使用的,所以,每当我想增加一个方法的时候,我必须先在接口声明一个方法,然后再在实现类里实现它。如此使用接口,只能说明我们没有深刻的掌握接口编程的思想。
大家能发现上面的问题吗?如果你们把面向接口编程思想吃透的话,那么就有了一定的鉴赏力,就可以发现其中的问题了。
我给大家说一下上面的代码存在什么问题吧!他本意是使用面向接口编程思想,但实际上变是面向对象编程思想。好比是,我本来想做大米汤呢,结果我却做成蒸大米饭。
上面的代码:外壳是面向接口编程,思想仍然是面向对象的。
换句话说:代码的表现形式是面向接口编程,而思想仍然是面向对象编程。因为它接口定义的太复杂了,定义接口相当于定义了父类,完成实现类相当于子类重写了父类的方法。
所以,大家定义接口一定要精炼,只有这样才能让思维有张力,才能突破物种这个观念。
面向对象编程和面向接口编程是Java的基础,最终是要统一起来的,如何实现统一的呢?
大家可以看下面的三行代码:
ArrayList<String> temp = new ArrayList<String>();
AbstractList<String> list1 = temp;//子类赋值给父类
List<String> list2 = temp;//类赋值给接口
第一行代码生成了一个对象temp
第二代码将对象赋值给父类list1;
第三行代码将对象赋值给接口list2;
从上面三行代码可以看出来,对象值是可以赋值父类变量,也可以赋值给接口变量,它的底层实现,是通过temp对象的Class对象的父类和接口实现来完成的。所以说,面向对象编程思想和面向接口编程思想都是通过类的Class对象来实现的。
通过我的编程经验,我觉得正确的面向接口编程思想,有两个规范。
(1)接口中声明的方法一定要精炼。因为接口不是父类,不要设计的过于冗余。MyBatis框架就做到很好,接口设计的非常精炼。
(2)接口既可以当做一类对象的公共方法模板,也可以将毫无相关的类,通过接口上溯成一类事物。在JDK中就存在不少这样的接口,例如AutoCloseable接口,Serializable接口等。
好了,今天的公开课就讲到这里了。讲的比较快,希望大家慢慢领悟吧。