【转载】JAVA中综合接口和抽象类实现的一种“抽象接口”
Muscleape个人总结:(这里的抽象接口是指:使用一个抽象类实现一个接口,是两部分结构)
使用一个抽象类直接实现接口,将接口中的方法区分为实现类必须要实现的和选择性实现的,其他需要实现接口的类型通过继承这个抽象类的方式实现接口,这样在具体的实现类中可以不用重写接口中用不到的方法,如果后期接口中新增加了方法,只需要在抽象类中重写新方法,具体的实现类需要使用该方法的才去重写该方法,其他的实现类可以不用做任何修改;
JAVA中的“抽象接口”(原博文名称)
在程序设计过程中,读者很可能遇到这样一种困境:设计了一个接口,但实现这个接口的子类并不需要实现接口中的全部方法,也就是说,接口中的方法过多,对于某些子类是多余的,我们不得不浪费的写上一个空的实现。
今天小菜提到的“抽象接口”,就是用来解决这个问题的。
为了不误导读者,先说明一下,什么是“抽象接口”。
所谓“抽象接口”,即在提供接口的同时,提供一个抽象类,用抽象类实现该接口(实际上这是缺省适配模式)。
下面小菜举个例子,让读者体会这样做的好处。
代码写的不咋地,为了防止读者看不懂,先上一张类图:

具体代码:
ITestInterface.java

1 /*
2 假设有一个顶层接口
3 */
4 public interface ITestInterface{
5 void method1();
6 int method2();
7 boolean method3();
8 }

TestAbstract.java

1 /*
2 抽象类abstract实现了ITestInterface顶层接口
3 */
4
5 public abstract class TestAbstract implements ITestInterface{
6 //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
7 public abstract void method1();
8 public abstract int method2();
9
10 //一些独特的方法可以在抽象类中默认实现
11 public boolean method3(){
12 return true;
13 }
14 }

TestClass1.java

1 /*
2 普通类TestClass1继承了TestAbstract抽象类
3 */
4
5 public class TestClass1 extends TestAbstract{
6
7 //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 1;
14 }
15
16 //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
17 }

TestClass2.java

1 /*
2 普通类TestClass2继承了TestAbstract抽象类
3 */
4
5 public class TestClass2 extends TestAbstract{
6
7 //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 2;
14 }
15
16 //method3方法对于TestClass2来说至关重要,因此必须重写。
17 public boolean method3(){
18 return false;
19 }
20
21 }

代码精讲:
从以上例子可以看出,最高层的接口被一个抽象类实现,在抽象类中,我们把关键的method1、method2方法定义成抽象方法,强制子类去实现,而“独特”的method3方法在抽象类中做一个默认实现。
等到TestClass1、TestClass2继承TestAbstract抽象类时,优势就体现出来了,TestClass1、TestClass2必须实现method1、method2,但如果用不到method3,可以直接无视。
通过接口和抽象类的结合,避免了在实现接口的子类中出现大量的“无意义”实现,这个“无意义”实现,被缓冲到了抽象类中,完美展现了代码复用(可以把抽象类理解成接口和实现类之间的缓冲)。
需要指出的是,我们既可以选择继承抽象类,也可以选择实现接口,并不是说一定要继承抽象类,看情况而定,这里是两种选择,两个机会。
写到这,或许读者觉得文章已经结束了,其实没有。。。
这样做的好处不仅仅是这一点,细细品味,假如我们向接口中增加了一个方法。。。
具体代码:
温馨提示:不要被代码吓到,其实这些代码和上边的差不多,只不过加了个方法而已。
ITestInterface.java

1 /*
2 假设有一个顶层接口
3 */
4 public interface ITestInterface{
5 void method1();
6 int method2();
7 boolean method3();
8 //接口中新增加了方法
9 String method4();
10 }

TestAbstract.java

1 /*
2 抽象类abstract实现了ITestInterface顶层接口
3 */
4
5 public abstract class TestAbstract implements ITestInterface{
6 //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
7 public abstract void method1();
8 public abstract int method2();
9
10 //一些独特的方法可以在抽象类中默认实现
11 public boolean method3(){
12 return true;
13 }
14
15 //抽象类中提供一个默认实现,这样就可以避免"惊动"所有子类
16 public String method4(){
17 return "";
18 }
19 }

TestClass1.java

1 /*
2 普通类TestClass1继承了TestAbstract抽象类
3 */
4
5 public class TestClass1 extends TestAbstract{
6
7 //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 1;
14 }
15
16 //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
17
18 //新增的方法对于TestClass1来说至关重要,因此必须重写
19 public String method4(){
20 return "Class1";
21 }
22
23 }

TestClass2.java

1 /*
2 普通类TestClass2继承了TestAbstract抽象类
3 */
4
5 public class TestClass2 extends TestAbstract{
6
7 //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 2;
14 }
15
16 //method3方法对于TestClass2来说至关重要,因此必须重写。
17 public boolean method3(){
18 return false;
19 }
20
21 //新增的方法对于TestClass2来说无关紧要,无需知道新增method4的存在
22 }

代码精讲:
这段代码演示了假如项目已经成型,但是需求有变,我们不得不向接口中增加一个新的方法,假如子类直接实现了接口,那么这些子类都要修改,来实现接口新增的方法。
但本例中的TestClass1、TestClass2子类没有直接实现接口,而是通过继承抽象类间接实现接口,这样好处一下就体现出来了!
向接口中新增的方法,可以在实现接口的抽象类中缓冲一下,提供一个默认的实现,这样一来,就不必强制所有的子类(通过继承抽象类间接实现接口的类)都进行修改,可以形象的理解为“没有惊动子类”。而需要使用这个方法的子类,直接重写即可。
小菜感慨:
人类的智慧真伟大!数组和链表结合,产生了高效的哈希表;接口和抽象类结合,产生了优雅的缺省适配模式。大家努力吧!!!
写在后面的话:
世间没有完美的事物,设计模式也是如此,过多的讨论优缺点没有意义,合适的就是最好的,什么是合适的呢?这才是体现智慧的地方。
【转载】JAVA中综合接口和抽象类实现的一种“抽象接口”的更多相关文章
- [转载]java中import作用详解
[转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...
- Java中的集合(七)双列集合顶层接口------Map接口架构
Java中的集合(七)双列集合顶层接口------Map接口 一.Map接口的简介 通过List接口,我们知道List接口下的集合是单列集合,数据存储是单列的结构.Map接口下是一个键值对(key-v ...
- Java中的集合(三)继承Collection的Queue接口
Java中的集合(三)继承Collection的Queue接口 一.Queue介绍 Queue接口继承自Collection接口,是Java中定义的一种队列数据结构,元素是有序的(按插入顺序排序),先 ...
- [转载]Java中继承、装饰者模式和代理模式的区别
[转载]Java中继承.装饰者模式和代理模式的区别 这是我在学Java Web时穿插学习Java设计模式的笔记 我就不转载原文了,直接指路好了: 装饰者模式和继承的区别: https://blog.c ...
- [转载]Java中异常的捕获顺序(多个catch)
http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) ...
- Java中的集合(六)继承Collection的Set接口
Java中的集合(六)继承Collection的Set接口 一.Set接口的简介 Set接口和List接口都是继承自Collection接口,它与Collection接口中功能基本一致,并没有对Col ...
- Java中的集合(五)继承Collection的List接口
Java中的集合(五)继承Collection的List接口 一.List接口简介 List是有序的Collection的,此接口能够精确的控制每个元素插入的位置.用户能够根据索引(元素在List接口 ...
- Java中创建(实例化)对象的五种方式
Java中创建(实例化)对象的五种方式1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运用反 ...
- 如何在java中跳出当前多重嵌套循环?有几种方法?
如何在java中跳出当前多重嵌套循环?有几种方法? - 两种方法 - 1.在外层循环定义标记 ok: for(int i=0;i<100;i++){ ...
随机推荐
- CLR类型设计之泛型(二)
在上一篇文章中,介绍了什么是泛型,以及泛型和非泛型的区别,这篇文章主要讲一些泛型的高级用法,泛型方法,泛型接口和泛型委托,协变和逆变泛型类型参数和约束性,泛型的高级用法在平时的业务中用的不多,多用于封 ...
- innobackupex: fatal error: no ‘innodb_buffer_pool_filename’解决方法
http://www.ttlsa.com/mysql/innobackupex-1-5-1-fatal-error-no-innodb_buffer_pool_filename/
- springboot整合shiro
请大家在看本文之前,先了解如下知识点: 1.Shiro 是什么?怎么用? 2.Cas 是什么?怎么用? 3.最好有Spring基础 可以先看看这两篇文章,按照这2篇文章的内容做一遍: Spring B ...
- 使用Jedis操作redis 缓存
案例:http://blog.csdn.net/linlzk/article/details/41801391 Redis是一个开源的Key-Value数据缓存,和Memcached类似. Redis ...
- Redis Save 与 BGSAVE 的区别
一,save保存数据到磁盘的方式: Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘. 语法redis Sav ...
- C#表达式目录树(Expression)
1.什么是表达式目录树 :简单的说是一种语法树,或者说是一种数据结构(Expression) 2.用Lambda声明表达式目录树: Expression<Func<; //表达试目录树的方 ...
- angular2.x指令
1.指令 *ngIf: 判断 isActive 为true时 <user-detail> 生效展示 <user-detail *ngIf="isActive"&g ...
- Java爬虫框架WebMagic——入门(爬取列表类网站文章)
初学爬虫,WebMagic作为一个Java开发的爬虫框架很容易上手,下面就通过一个简单的小例子来看一下. WebMagic框架简介 WebMagic框架包含四个组件,PageProcessor.Sch ...
- HTML Entity 字符实体
目录 1. HTML Entity 2. 字符与Entity Name的互相转换 3. 字符与Entity Number的互相转换 1. HTML Entity 1.1 介绍 在编写HTML页面时,需 ...
- NETStandard,NETFx,Mono,NETCore,ASPNetCore 之间关系的整理
因为现在很多人对这几者之间的关系还不甚了解,这里根据我所知来做一个大概的介绍...... .NET Standard: .NET标准,只要符合这个标准实现类库,即可在支持此标准的Run ...