文档章节

JAVA中的“抽象接口”

ForingY
 ForingY
发布于 2016/02/26 15:51
字数 1564
阅读 56
收藏 2

 在程序设计过程中,读者很可能遇到这样一种困境:设计了一个接口,但实现这个接口的子类并不需要实现接口中的全部方法,也就是说,接口中的方法过多,对于某些子类是多余的,我们不得不浪费的写上一个空的实现。

       今天小菜提到的“抽象接口”,就是用来解决这个问题的。

       为了不误导读者,先说明一下,什么是“抽象接口”。

       所谓“抽象接口”,即在提供接口的同时,提供一个抽象类,用抽象类实现该接口(实际上这是缺省适配模式)。

       下面小菜举个例子,让读者体会这样做的好处。

       代码写的不咋地,为了防止读者看不懂,先上一张类图:

具体代码:

  ITestInterface.java

复制代码

/*
    假设有一个顶层接口
*/
public interface ITestInterface{
    void method1();
    int method2();
    boolean method3();
}

复制代码

 

 

  TestAbstract.java

复制代码

/*
    抽象类abstract实现了ITestInterface顶层接口
*/

public abstract class TestAbstract implements ITestInterface{
    //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
    public abstract void method1();
    public abstract int method2();
    
    //一些独特的方法可以在抽象类中默认实现
    public boolean method3(){
        return true;
    }
}

复制代码

 

  

  TestClass1.java

复制代码

 /*
    普通类TestClass1继承了TestAbstract抽象类
*/

public class TestClass1 extends TestAbstract{
    
    //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
    public void method1(){
        
    }
    //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
    public int method2(){
        return 1;
    }
    
    //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
}

复制代码

 

 

  TestClass2.java

复制代码

 /*
    普通类TestClass2继承了TestAbstract抽象类
*/

public class TestClass2 extends TestAbstract{
    
    //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
    public void method1(){
    
    }
    //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
    public int method2(){
        return 2;
    }
    
    //method3方法对于TestClass2来说至关重要,因此必须重写。
    public boolean method3(){
        return false;
    }
    
}

复制代码

 

 

代码精讲:

    从以上例子可以看出,最高层的接口被一个抽象类实现,在抽象类中,我们把关键的method1、method2方法定义成抽象方法,强制子类去实现,而“独特”的method3方法在抽象类中做一个默认实现。

    等到TestClass1、TestClass2继承TestAbstract抽象类时,优势就体现出来了,TestClass1、TestClass2必须实现method1、method2,但如果用不到method3,可以直接无视。

    通过接口和抽象类的结合,避免了在实现接口的子类中出现大量的“无意义”实现,这个“无意义”实现,被缓冲到了抽象类中,完美展现了代码复用(可以把抽象类理解成接口和实现类之间的缓冲)。

    需要指出的是,我们既可以选择继承抽象类,也可以选择实现接口,并不是说一定要继承抽象类,看情况而定,这里是两种选择,两个机会。

      

              写到这,或许读者觉得文章已经结束了,其实没有。。。

              这样做的好处不仅仅是这一点,细细品味,假如我们向接口中增加了一个方法。。。

 

具体代码:

  温馨提示:不要被代码吓到,其实这些代码和上边的差不多,只不过加了个方法而已。

 

  ITestInterface.java

复制代码

/*
    假设有一个顶层接口
*/
public interface ITestInterface{
    void method1();
    int method2();
    boolean method3();
    //接口中新增加了方法
    String method4();
}

复制代码

 

 

  TestAbstract.java

复制代码

 /*
    抽象类abstract实现了ITestInterface顶层接口
*/

public abstract class TestAbstract implements ITestInterface{
    //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
    public abstract void method1();
    public abstract int method2();
    
    //一些独特的方法可以在抽象类中默认实现
    public boolean method3(){
        return true;
    }
    
    //抽象类中提供一个默认实现,这样就可以避免"惊动"所有子类
    public String method4(){
        return "";
    }
}

复制代码

 

 

  TestClass1.java

复制代码

/*
    普通类TestClass1继承了TestAbstract抽象类
*/

public class TestClass1 extends TestAbstract{
    
    //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
    public void method1(){
        
    }
    //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
    public int method2(){
        return 1;
    }
    
    //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
    
    //新增的方法对于TestClass1来说至关重要,因此必须重写
    public String method4(){
        return "Class1";
    }

}

复制代码

 

 

  TestClass2.java

复制代码

/*
    普通类TestClass2继承了TestAbstract抽象类
*/

public class TestClass2 extends TestAbstract{
    
    //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
    public void method1(){
    
    }
    //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
    public int method2(){
        return 2;
    }
    
    //method3方法对于TestClass2来说至关重要,因此必须重写。
    public boolean method3(){
        return false;
    }
    
    //新增的方法对于TestClass2来说无关紧要,无需知道新增method4的存在
}

复制代码

 

 

代码精讲:

    这段代码演示了假如项目已经成型,但是需求有变,我们不得不向接口中增加一个新的方法,假如子类直接实现了接口,那么这些子类都要修改,来实现接口新增的方法。

    但本例中的TestClass1、TestClass2子类没有直接实现接口,而是通过继承抽象类间接实现接口,这样好处一下就体现出来了!

    向接口中新增的方法,可以在实现接口的抽象类中缓冲一下,提供一个默认的实现,这样一来,就不必强制所有的子类(通过继承抽象类间接实现接口的类)都进行修改,可以形象的理解为“没有惊动子类”。而需要使用这个方法的子类,直接重写即可。

 

小菜感慨:

 

    人类的智慧真伟大!数组和链表结合,产生了高效的哈希表;接口和抽象类结合,产生了优雅的缺省适配模式。大家努力吧!!!

 

写在后面的话:

    世间没有完美的事物,设计模式也是如此,过多的讨论优缺点没有意义,合适的就是最好的,什么是合适的呢?这才是体现智慧的地方。


© 著作权归作者所有

共有 人打赏支持
ForingY
粉丝 23
博文 272
码字总数 156129
作品 0
杭州
程序员

暂无文章

Spring Cloud Gateway真的有那么差吗?

前言 Spring Cloud从一开始最受大家质疑的就是网关性能,那是由于Spring Cloud最初选择了使用Netflix几年前开源的Zuul作为基础,而高性能版的Zuul 2在经过了多次跳票之后,对于Spring这样的整...

Java小铺
36分钟前
1
0
SpringBoot远程调试,远程debug你的线上项目

开发环境中代码出错了,可以利用IDE的debug功能来进行调试。那线上环境出错呢? 一、假设我们的项目是部署在tomcat中,那我们就需要对tomcat进行一定对配置,配置如下。 1. windows系统中,找...

nonnetta
41分钟前
0
0
JAVA秒杀优化方向

秒杀优化方向 将请求尽量拦截在系统上游:传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,几乎所有请求都超时,流量虽大,下单成功的有效流量甚小,我们可以通过限流、...

小贱是个程序员
49分钟前
0
0
C# 统计字符串中大写字母和小写字母的个数

static void Main() { int count1 = 0; int count2 = 0; Console.WriteLine("请输入字符串"); string str = Convert.ToString(Consol......

熊二的爸爸是谁
51分钟前
0
0
分布式服务框架之远程通讯技术及原理分析

在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是...

老道士
56分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部