接口,抽象类的使用以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么
接口,抽象类的使用
以前在使用接口的时候,就知道它可以抽象系统模型,便于扩展。但到底什么时候使用接口,什么时候使用抽象类,我一直也不是很清楚。但最新做了一个项目,其中遇到抽象一个系统模型的时候,让我明白了他们的用途。废话少说,直接上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类作为项目实际需求,可以实现文件读入流的获取和关闭,实现了一些共同行为。
我想这就是接口和抽象类的最大区别了吧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()方法。
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修改为借口,那么这两个接口之间不需要有任何关系,实现类就可以同时实现他们的抽象方法了。
33 楼 puroc 2008-11-21 我的做法是,如果一个类就能实现功能的话,绝对不为其定义一个抽象类或者接口。如果以后有需求的话,在增加也来得及。如果是有多个实现的话,那么我一般定义为接口,如果这多个实现类有可以复用的方法时,就把这些提到一个抽象类中,让这个抽象类实现接口,然后所有的实现类继承这个抽象类。