`
卒子99
  • 浏览: 73689 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

接口,抽象类的使用

阅读更多
   以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么时候使用抽象类,我一直也不是很清楚。但最新做了一个项目,其中遇到抽象一个系统模型的时候,让我明白了他们的用途。废话少说,直接上Case了
  需求:从文件中系统中读取数据,可支持从TXT文件,XML,XLS.....

  这个是最初的需求,很简单,系统支持从多文件格式读取数据,首先抽象出一个AbstractFileDataParser类,类图如下:
AbstractFileDataParser类代码如下:
public abstract class AbstractFileDataParser
{
    private FileInputStream fileInputStream = null;

    public AbstractFileDataParser(FileInputStream fileInputStream)
    {
        if (fileInputStream == null)
        {
            throw new NullPointerException("file input stream is null!");
        }
        this.fileInputStream = fileInputStream;
    }

    protected FileInputStream getFileInputStream()
    {
        return this.fileInputStream;
    }

    public void release()
    {
        CloseUtil.close(fileInputStream);
    }

}

   最主要的方法就是readData,类似于BufferedReader,每次调用读取一组数据,如果还回Null,表示数据读取完成了。
   如果从项目的需要上来看,这个抽象应该是满足需求了。但现在有考虑问题,会老想着抽象,所以又想了到了一个新的抽象层:只是读取数据。这就意味着不知道什么地方获取数据,文件系统,网络等,于是需要进一步抽象,这个时候就需要定义一个IDataParser接口,类图抽象层次如下所示
IDataParser接口代码如下:

public interface IDataParser
{
    /**
     * 
     * 如果还回null,则代表没有可读取的数据了 
     * 
     * @return
     */
    Object[] readData();

    void release();

}

AbstractFileDataParser类实现IDatParser接口,代码如下:
public abstract class AbstractFileDataParser implements IDataParser
{
    private FileInputStream fileInputStream = null;

    public AbstractFileDataParser(FileInputStream fileInputStream)
    {
        if (fileInputStream == null)
        {
            throw new NullPointerException("file input stream is null!");
        }
        this.fileInputStream = fileInputStream;
    }

    protected FileInputStream getFileInputStream()
    {
        return this.fileInputStream;
    }

    public void release()
    {
        CloseUtil.close(fileInputStream);
    }
}


   这个抽象层次就比较清楚了,虽然暂时项目中只是从文件中读取数据,但并不保证以后可能会改变啊,抽象出一个接口,就很好满足了OCP。而AbstractFileDataParser类作为项目实际需求,可以实现文件读入流的获取和关闭,实现了一些共同行为。
   我想这就是接口和抽象类的最大区别了吧
  • 描述: AbstractFileDataParser
  • 大小: 1.9 KB
  • 描述: 抽象层次
  • 大小: 3 KB
分享到:
评论
33 楼 puroc 2008-11-21  
我的做法是,如果一个类就能实现功能的话,绝对不为其定义一个抽象类或者接口。如果以后有需求的话,在增加也来得及。如果是有多个实现的话,那么我一般定义为接口,如果这多个实现类有可以复用的方法时,就把这些提到一个抽象类中,让这个抽象类实现接口,然后所有的实现类继承这个抽象类。
32 楼 puroc 2008-11-21  
grandboy 写道
思想有时不太好表达。有的时候就是那种“只可以意会,不可言传”的感觉。还是就lz的代码谈, 如果我没有理解错的话,楼主的那个接口真是有点多余。其实只要一个抽象类里面再定义一个抽象方法就行了。不能为了接口而接口。代码如下:
public abstract class AbstractFileDataParser 
{  
    private FileInputStream fileInputStream = null;  
  
    public AbstractFileDataParser(FileInputStream fileInputStream)  
    {  
        if (fileInputStream == null)  
        {  
            throw new NullPointerException("file input stream is null!");  
        }  
        this.fileInputStream = fileInputStream;  
    }  
  
    protected FileInputStream getFileInputStream()  
    {  
        return this.fileInputStream;  
    }  
  
    public void release()  
    {  
        CloseUtil.close(fileInputStream);  
    }  
    
    abstract Object[] readData();  
}


然后在子类里就可以实现这个readData()方法。



同意不能为了接口而接口的说法。像兄台这样,把这个方法定义为抽象方法。然后用实现类去实现他,没有问题。但如果现在还有另外一个抽象类B,也定义了一个抽象方法,而刚才那个实现类,也需要实现抽象类B的抽象方法。应该就没办法写了,除非让这个抽象类B继承你的抽象类,这样实现类才可以实现这两个抽象方法。但如果把你的抽象类和抽象类B修改为借口,那么这两个接口之间不需要有任何关系,实现类就可以同时实现他们的抽象方法了。
31 楼 mooniscrazy 2008-11-18  
接口对外,抽象类对内。
接口是战略层面的,抽象类是战术层面的。
抽象类的出现,只是为了省几行代码,没有它也是无所谓的。
抽象类,一般只有少数几个类使用它。而且,有可能存在几个不同的抽象类。
抽象类不能当作接口使用。
之所以会在这个问题上有疑惑,说明对创建型模式理解不正确。
仔细想想如何创建这个抽象类,想想如何屏蔽抽象类的实现细节,然后在想想出现几个抽象类的情况,想明白了就不会暴露抽象类了。
抽象类的正确用法,就是在包内部使用。应该是default访问修饰符。或者是更小的protected,不应该是public。
30 楼 sea7 2008-11-17  
williamy 写道
1,抽象類就是爲了extends的
2,interface是爲了多態的
如果你看過多繼承,那麽你就明白interface是多餘的,
interface害死人啊,java莫名其妙的來個interface
就是爲了讓那些沒看過c++的人明白怎麽實現多繼承
並且,其實還是一個假的多繼承


晕...

接口实现的是一种契约的关系,而抽象类实现的才是继承的关系.
29 楼 cjjer 2008-10-20  
接口一般对的事外面扩展和快速引用。关心的是事情本身的实现方法或者一个路径而已。
抽象类一般可以做两件事情,内部的松耦合;逻辑实现。关心的是具体的实现。
28 楼 xixix2004 2008-10-15  
看了楼上的帖子真的想说大家都是地道的程序员。

可是接口的引用并不源于编程,而是现实生活中的设计。针对编码中的接口和抽象类谁好谁坏进行争论是毫无意义的。同理也包括针对接口的使用是否有必要这样的争论。

之前楼上有人说“接口是针对外部使用者,而抽象类是针对内部”这样的观点就很精辟了。想想看为什么你家插座上的插孔都是二头三头,而内部线路的排放却千差万别就知道了。因为插座是提供给外部使用的。

面向接口的编程确实听起来很时髦,但是先想想有没有必要,是不是一定要用接口。一些规模小的公司的程序员会说,完全没必要,我们不用接口做出来的项目一样过硬,一些大公司的程序员会说,接口是必须的。

这是为什么?不是他们的项目差别有多大,而且就算不用接口也不会影响运行效率。而是因为,大公司里人员比较多,在多人共同开发一个项目的时候,他们需要设计一个或者若干个接口来作为一个标准,才不至于使项目的开发显得混乱。

也就是说接口的使用与否在代码层面完全无关紧要。

虽然这样说有人会觉得我藐视接口的作用,呵呵,经历过就会知道了。
27 楼 gnomewarlock 2008-10-14  
world123 写道
public class Cellphone extends Phone implements Bluetooth{  
}

这个比喻比较牛逼
26 楼 world123 2008-09-18  
public class Cellphone extends Phone implements Bluetooth{  
}
25 楼 czlonly 2008-09-17  
我感觉抽象类就是一类具有共性的对象的抽象表现,抽象类的方法表现了共同的动作与行为,而接口所描述的动作或行为,只是用了一个形象的描述名称,其具体内容要视实现它的类来决定
24 楼 ddppfamily 2008-09-17  
看了楼主的帖子,突然感觉大脑好~~~~清醒。
23 楼 liqiaoyuan 2008-09-16  
如果一个类已经继承别的类!它还能继承抽象类么?这时只能使用接口,其实接口就是一个特殊的抽象类。我觉得在实际开发中,尽量少使用抽象类。不知道我说的对不对,如果不对请大家给点建议。
22 楼 grandboy 2008-09-14  
思想有时不太好表达。有的时候就是那种“只可以意会,不可言传”的感觉。还是就lz的代码谈, 如果我没有理解错的话,楼主的那个接口真是有点多余。其实只要一个抽象类里面再定义一个抽象方法就行了。不能为了接口而接口。代码如下:
public abstract class AbstractFileDataParser 
{  
    private FileInputStream fileInputStream = null;  
  
    public AbstractFileDataParser(FileInputStream fileInputStream)  
    {  
        if (fileInputStream == null)  
        {  
            throw new NullPointerException("file input stream is null!");  
        }  
        this.fileInputStream = fileInputStream;  
    }  
  
    protected FileInputStream getFileInputStream()  
    {  
        return this.fileInputStream;  
    }  
  
    public void release()  
    {  
        CloseUtil.close(fileInputStream);  
    }  
    
    abstract Object[] readData();  
}


然后在子类里就可以实现这个readData()方法。
21 楼 HRoger 2008-09-09  
我觉得用继承是为了达到复用,用接口是为了达到灵活(松耦合),权衡二者的利弊之后再决定
20 楼 bonny 2008-07-24  
接口做名词
抽象类做动词

框架主要是抽象类+工厂。
19 楼 allaneiaaa 2008-07-24  
一般会分离实现的。不会abstract class AbstractFileDataParser implements IDataParser。而是采用注入的方式。比较好。 典型的策略或者模板设计模式。
18 楼 taowen 2008-06-30  
楼主需要的接口可以简化为
Iterable<YourDataType>
17 楼 zfyyfz 2008-05-05  
我觉得抽象内和继承相关,比如拿文档类来说,都有title,time属性,并且getTime,setTime都是相同方法,就用抽象类处理;
接口运用比较广泛,大多为了解耦,使高层完全不用知道子类的变换和约定的一个协约,这样高层就不再依赖底层。灵活调用,当底层发生变化时也完全不用通知高层。
16 楼 WorldHello 2008-04-29  
从面向对象分析与设计的角度来说:
abstract class表示“is-a”的关系,即父类与继承类本质上一致的;
对于interface,并不要求interface的实现者和interface定义在概念本质上是一致的, 只表示一种契约关系,可以将interface看成“like-a”或者“has-a”的关系(这种说法不是很准确)。

举例来说:电视机、收音机同属电器,具有打开,关闭,调台的方法;同时电视机、收音机都有遥控器(收音机带遥控器的好像不多!)。

类结构如下:
abstract class 电器{
       public void 打开(){}
       public void 关闭(){}
       public void 调台(){}
}

interface 遥控器{
      void 遥控(){}
}

class  电视机 extends 电器 implements 遥控器{
       //重写方法,略
}
class  收音机 extends 电器 implements 遥控器{
       //重写方法,略
}
15 楼 Ab.Yann 2008-04-29  
同意楼上所说的:interface关注的是外部的使用者,而Abstract Class是对内的。

接口是定义了一些规格(规则),这些规格是对外的.
抽象类则是对内部变化的一种封装.
14 楼 joachimz 2008-04-19  
williamy 写道
1,抽象類就是爲了extends的
2,interface是爲了多態的
如果你看過多繼承,那麽你就明白interface是多餘的,
interface害死人啊,java莫名其妙的來個interface
就是爲了讓那些沒看過c++的人明白怎麽實現多繼承
並且,其實還是一個假的多繼承


忍不住要晒一下观点:interface是约定的contract,对外部调用者的承诺,设计精髓的体现(对象的职责)。良好的interfacer设计可以保证边界清晰、程序的稳定、真正的松耦合。
而Abstract Class是对内部实现的一个基础,最多只是对内部实现提供一些重用而已。或者说,interface关注的是外部的使用者,而Abstract Class是对内的。
并且在复杂的环境下,继承会带来许多副作用。继承层次多,或者扩展点过多时,增加一个子类绝对是一个灾难:需要了解大量父类的内部实现细节,例如经典的Template Method、Strategy等模式。组合应该是更好的实现方式。

我的理解,面向对象更重要的是,保持整体结构的清晰、模块的松耦合。而不是小范围的重用问题。Procedure/Function的重用也可以很好,甚至更简单、容易。

相关推荐

    C#抽象类与接口方法

    抽象类与接口 抽象类与接口 抽象类与接口 抽象类与接口

    java抽象类与接口实例java抽象类与接口实例

    java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例java抽象类与接口实例...

    Java抽象类与接口实验报告

    Java抽象类与接口实验报告

    详细解析Java中抽象类和接口的区别

    抽象类和接口的区别 在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。abstract class和interface之间在对于抽象类定义的支持...

    Java继承_抽象类与接口的应用.

    1.继承及继承实例 2.方法重写(Overwrite) 3.super关键字 4.方法重载(Overload) 5.final修饰符 6.abstract修饰符 7.抽象类 8.接口 9.接口和抽象类对比 10.接口和抽象类使用场合实例 11.总结

    抽象类和接口实验报告.doc

    抽象类和接口实验报告

    C#接口抽象类区别实例

    c#中抽象类和接口。 相同点: (1) 都可以被继承 (2) 都不能被实例化 (3) 都可以包含方法声明 (4) 派生类必须实现未实现的方法 区 别: (1) 抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、...

    接口与抽象类区别

    主要介绍接口与抽象类的区别,为那些困惑的人指点迷津。

    抽象类和接口

    1. 设计并使用抽象类; 2.学习如何定义接口,掌握接口的实现方式,使用实现了接口的类; 3.理解接口与抽象类的区别。

    C#类、接口、虚方法和抽象方法-抽象类和接口的相同点和区别

    (3) 抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明为抽象类 (4) 具体派生类必须覆盖基类的抽象方法 (5) 抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。如果不覆盖,...

    接口和抽象类使用详细实例源代码

    1 抽象类&&接口,是什么 2 依赖抽象,为什么用 3 二者的区别与选择 代码实现比较。

    C#类、接口、虚方法和抽象方法-接口与抽象类的区别实例

    C#类、接口、虚方法和抽象方法-接口与抽象类的区别实例 C#类、接口、虚方法和抽象方法-接口与抽象类的区别实例

    11.java接口和抽象类的区别.zip

    11.java接口和抽象类的区别.zip11.java接口和抽象类的区别.zip11.java接口和抽象类的区别.zip11.java接口和抽象类的区别.zip11.java接口和抽象类的区别.zip11.java接口和抽象类的区别.zip11.java接口和抽象类的区别....

    java 抽象类与接口的练习

    java 抽象类与接口的练习,包括代码及注释,个人笔记

    Java中抽象类和接口的区别

    在Java语言中,abstract class和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,...

    Java 接口和抽象类

    Java 接口和抽象类

    10.java接口和抽象类的相似性.zip

    10.java接口和抽象类的相似性.zip10.java接口和抽象类的相似性.zip10.java接口和抽象类的相似性.zip10.java接口和抽象类的相似性.zip10.java接口和抽象类的相似性.zip10.java接口和抽象类的相似性.zip10.java接口和...

    1.5:接口和抽象类的区别.pdf

    4.实现抽象类和接口的类必须实现其中的所有方法。 抽象类中可以有非抽象方法。接口中则不能有实现方法。如果接口或者抽象类的子类不想实现则继续携程一个抽象方法 5.接口中定义的变量默认是public static final ...

    抽象类和接口练习

    学习java的抽象类和接口,入门抽象类和接口必须学会这些内容

    基于Java抽象类和接口实现疯狂动物城

    本实验手册即根据需求模拟完成一个简易的疯狂动物城游戏系统, 平台的全称为:使用抽象类和接口实现疯狂动物城项目(后简称为: crazyZoo) 。该系统的主要功能包括:查看动物城成员、入驻动物城、修改动物信息、查找疯狂...

Global site tag (gtag.js) - Google Analytics