学习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了。