2008-02-24

接口,抽象类的使用

关键字: 接口 抽象类
以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么时候使用抽象类,我一直也不是很清楚。但最新做了一个项目,其中遇到抽象一个系统模型的时候,让我明白了他们的用途。废话少说,直接上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类作为项目实际需求,可以实现文件读入流的获取和关闭,实现了一些共同行为。
我想这就是接口和抽象类的最大区别了吧
  • Fd618570-1ce4-3487-b6c1-f906cc319781-thumb
  • 描述: AbstractFileDataParser
  • 大小: 1.9 KB
  • 9a7b8bb5-0a08-3a99-9dda-c7ea08693542-thumb
  • 描述: 抽象层次
  • 大小: 3 KB
评论
taowen 2008-06-30
楼主需要的接口可以简化为
Iterable<YourDataType>
hunter001201 2008-06-30
对于lz的设计
我建议 如果是 "多文件格式读取数据"行为,你可以设计成接口
如果是"多文件格式读取数据器",你可以设计成抽象类
hunter001201 2008-06-30
抽象类与接口的关系,本质是类与接口的关系.

到底什么可以划分到类,什么需要借口? 你是怎么考虑的呢?

类是一些比较实在的,可以具体看到或感觉到的东西,各种水果,例如梨,苹果等.
接口指契约,规定.一般是描述一些动作行为. 比如飞翔,呼吸等.
zfyyfz 2008-05-05
我觉得抽象内和继承相关,比如拿文档类来说,都有title,time属性,并且getTime,setTime都是相同方法,就用抽象类处理;
接口运用比较广泛,大多为了解耦,使高层完全不用知道子类的变换和约定的一个协约,这样高层就不再依赖底层。灵活调用,当底层发生变化时也完全不用通知高层。
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 遥控器{
//重写方法,略
}
Ab.Yann 2008-04-29
同意楼上所说的:interface关注的是外部的使用者,而Abstract Class是对内的。

接口是定义了一些规格(规则),这些规格是对外的.
抽象类则是对内部变化的一种封装.
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的重用也可以很好,甚至更简单、容易。
zhangguoli1997 2008-04-18
我认为抽象类跟接口负责的功能是一样的!制定一些接口规范!其它的子类必须实现它们定义的未实现的方法!接口跟抽象类不同的地方是抽象类可以有一些方法里边有代码!当有一些代码是几个子类都有的时候就可以抽象到抽象类!如果没有公用的代码就用接口!就这么简单!
andy54321 2008-04-17
qmy 写道
williamy 写道
1,抽象類就是爲了extends的
2,interface是爲了多態的
如果你看過多繼承,那麽你就明白interface是多餘的,
interface害死人啊,java莫名其妙的來個interface
就是爲了讓那些沒看過c++的人明白怎麽實現多繼承
並且,其實還是一個假的多繼承

.....



这位说的太偏激了。。。。。
现在面向接口的编程不是很好很强大么,大家评价都蛮高的。
如果都用多继承而且没有interface的话,代码的黏合度不是很很高么?
这样对代码的简洁度、解耦合好像都是有些问题的。。

不知道说的对不对
qmy 2008-04-16
public class Cellphone extends Phone implements Bluetooth{
}
卒子99 2008-04-16

[quote="williamy"]2,interface是爲了多態的
如果你看過多繼承,那麽你就明白interface是多餘的,
interface害死人啊,java莫名其妙的來個interface
就是爲了讓那些沒看過c++的人明白怎麽實現多繼承
並且,其實還是一個假的多繼承[/quote]


interface就是用来实现多态的,和继承有关系吗?

例如,如果有一个基类叫做Person,现在我需要它具有一个父亲的特性,采用继承有关系,就如下

 public class Father extend Person

{
.........
public void readStoryToBaby(){}
}

 

又出现一个老板类,又会产生以下继续关系

 public class Father extend Person

{
public void meeting(){}
}


 

 

 

 

 

 最后事业有成了,又是孩子的父亲,又是老板,那怎么做呢?我不懂C++,大概可能是这样子的

 public class SuccessMan extend Father,Boss

{
pulbic void readStoryToBaby(){}
public void meeting(){}
}

 

这就会有一个问题了,在公司环境中,你的雇员可以让我们的Boss讲故事,而在家里,你的孩子可能会让你给他讲故事。在系统中是没有必要,也不应该讲其它方法暴露出来的。
而使用接口是很好的做到这点的

 public class SuccessMan implements Father,Boss

{
pulbic void readStoryToBaby(){}
public void meeting(){}
}

 

在工作环境中:

 public class WorkContext 

{
public WorkdContext(Boss boss){}
}

 

而在家里:

public class Home

{
public Home(Father father){}
}

 

这样不是会更优雅些吗?

williamy 2008-04-15
1,抽象類就是爲了extends的
2,interface是爲了多態的
如果你看過多繼承,那麽你就明白interface是多餘的,
interface害死人啊,java莫名其妙的來個interface
就是爲了讓那些沒看過c++的人明白怎麽實現多繼承
並且,其實還是一個假的多繼承
卒子99 2008-04-15
是不是我的意思没有表述清楚呢?
大家都在讨论这个到底是什么模式,
其实我只是想表述什么时候选择用接口,什么时候选择用抽象类
卒子99 2008-04-15
dearmite 写道
卒子99 写道
以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么时候使用抽象类,我一直也不是很清楚。但最新做了一个项目,其中遇到抽象一个系统模型的时候,让我明白了他们的用途。废话少说,直接上Case了
需求:从文件中系统中读取数据,可支持从TXT文件,XML,XLS.....


这个抽象层次就比较清楚了,虽然暂时项目中只是从文件中读取数据,但并不保证以后可能会改变啊,抽象出一个接口,就很好满足了OCP。而AbstractFileDataParser类作为项目实际需求,可以实现文件读入流的获取和关闭,实现了一些共同行为。
我想这就是接口和抽象类的最大区别了吧



我看了一下楼主的想法,

我的感觉可能和楼主不太一致!

从多种源中读数据,这个肯定是多个实现,不用说了,
如果我来设计,
如果只是读,只有一段代码的话,那就用接口好了,不为别的,干净!

如果是读了之后,还有一段都相同的处理代码,

那就使用抽象类好了。

写两个方法,

abstract String readXML()
{
}

void dealString()
{

String aa = this.readXML();
处理aa;
}

这样不是显得更好样一点???



确实,接口越简单越好,甚至可以只是一个标识接口
但是在实际运用中可以发现,对于这种动名词命令的接口(自己定义的),非常有必须留一个方法用于清除资源,就像Connection, Reader这样的
coreymylife 2008-04-04
确实是模板模式
所谓模板模式就是把一系列类中相同的部分抽取出来形成抽象,不同的方法不同实现!
dearmite 2008-04-04
用抽象类,来实现这种中间多层的实现,

23GOF里,叫模板的模式!


有现成的用别人的成果吧,这样比较省事!
dearmite 2008-04-04
卒子99 写道
以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么时候使用抽象类,我一直也不是很清楚。但最新做了一个项目,其中遇到抽象一个系统模型的时候,让我明白了他们的用途。废话少说,直接上Case了
需求:从文件中系统中读取数据,可支持从TXT文件,XML,XLS.....


这个抽象层次就比较清楚了,虽然暂时项目中只是从文件中读取数据,但并不保证以后可能会改变啊,抽象出一个接口,就很好满足了OCP。而AbstractFileDataParser类作为项目实际需求,可以实现文件读入流的获取和关闭,实现了一些共同行为。
我想这就是接口和抽象类的最大区别了吧



我看了一下楼主的想法,

我的感觉可能和楼主不太一致!

从多种源中读数据,这个肯定是多个实现,不用说了,
如果我来设计,
如果只是读,只有一段代码的话,那就用接口好了,不为别的,干净!

如果是读了之后,还有一段都相同的处理代码,

那就使用抽象类好了。

写两个方法,

abstract String readXML()
{
}

void dealString()
{

String aa = this.readXML();
处理aa;
}

这样不是显得更好样一点???
zfms 2008-04-04
楼主写的有些不是很明确,能在完善一些嘛?既然实现了IDataParser 接口,为什么没有接口实现?
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

卒子99
搜索本博客
最近加入圈子
存档
最新评论