学习Spring源码已经有一段时间了,对代码设计有了一些收获,因此记录一下。
我们常用到的类主要分为接口(interface)、抽象类(abstract class)以及实现类(class)。在代码中经常遇到这些java文件,在我学习Spring源码之前,更多是是生搬硬套,例如Dao层、Service层用interface,高级一点就是工厂模式、策略模式用一下interface,如果发现在设计模式中还有公共的方法,就可以将interface改用为abstract class。当然现在Java 8的interface已经支持default方法,这个就是后话了。Interface和abstract class都是要靠class来进行实现。对于初学者来说,interface和abstract class在定义上的区别应该都是比较清楚的,例如class只能继承1个abstract class,但是却可以实现多个interface。但是应用上的区别有什么区别呢,这个却比较模糊,特别是interface已经支持default方法后,interface和abstract class似乎也越来越接近。但是在应用层面来看,这两者还是有很大区别的。理解清楚这两者之间的区别,有利于更好的设计自己的代码。
首先,阐述一下我对interface和abstract class在应用层面的理解。总的来说interface是一组功能(方法)的集合,abstract class是对于1个对象的某些行为(方法)的抽象。假设一个抽象类Persion。假设2个interface,分别叫做MovingBrick和TeachingBook。
// 抽象类
public abstract class Persion
{
private String name;
private String sex;
private int age;
public abstract void move();
}
// 接口1
public interface MovingBrick
{
void findBrick();
void moveBrick();
}
// 接口2
public interface TeachingBook
{
void findBook();
void teachBook();
}
利用以上的interface和abstract class作为原材料,此时如果我们需要一个普通人的对象OrdinaryPersion,它的移动方式假设为run,那么应该如何构造呢?我们只需要OrdinaryPersion继承Persion,然后实现move方法即可,如下:
public class OrdinaryPersion extends Persion
{
@Override
public void move()
{
System.out.println("run");
}
}
如果我们需要一个会搬砖的普通人呢?此时我们只需要实现MovingBrick接口即可。
public class OrdinaryMovingBrickPersion extends Persion implements MovingBrick
{
@Override
public void findBrick()
{
System.out.println("findBrick");
}
@Override
public void moveBrick()
{
System.out.println("moveBrick");
}
@Override
public void move()
{
System.out.println("run");
}
}
如果我们需要一个又会搬砖又会教书的普通人呢?此时我们只需要同时实现MovingBrick和TeachingBook接口即可。
public class OrdinaryMovingBrickAndTeachingBookPersion extends Persion implements MovingBrick, TeachingBook
{
@Override
public void findBrick()
{
System.out.println("findBrick");
}
@Override
public void moveBrick()
{
System.out.println("moveBrick");
}
@Override
public void findBook()
{
System.out.println("findBook");
}
@Override
public void teachBook()
{
System.out.println("teachBook");
}
@Override
public void move()
{
System.out.println("run");
}
}
上面的例子可以看出来,abstract class要体现对象的本质属性与行为,与对象是强相关的,而interface更多的是体现功能,与对象的相关性就很低了。如果是Dog类来实现MovingBrick接口,那就是MovingBrickDog了。