Java接口和抽象类

前言

之前背八股的时候一直都搞不懂抽象类到底有什么用,只能硬背抽象类的概念,接口跟抽象类的区别。。。
最近在实现一个简单的spring框架的时候,突然感觉对接口和抽象类有点理解了。

正文

就拿下面这个继承关系来说,接口的作用是一种规范、一种基准,定义了你能做什么。
而抽象类的作用感觉更多的是职责,抽象类实现一个接口,可以只选择实现一部分方法,不要全部实现,
其他没实现的方法由子类去实现,分工明确,一个抽象类只负责部分功能。并且还可以实现其他接口,实现功能的扩展
这样最后继承抽象类的类就可以获取之前抽象类实现的所有功能,而不用把这些类都写到一个类中,显得臃肿
接口和抽象类

并且接口 → 抽象类 → 具体实现类这样的结构还利于扩展。
比如:

定义接口(只关心能力)

现在只规定了「你能通过名字拿到一个对象」。

public interface Container {
    Object getBean(String name);
}

抽象类(封装公共逻辑)

所有容器都会用「单例缓存」,所以这里把公共逻辑抽出来了。
但怎么创建对象(createBean)留给子类决定。

public abstract class AbstractContainer implements Container {
    private final Map<String, Object> singletonObjects = new HashMap<>();

    @Override
    public Object getBean(String name) {
        // 先从缓存找
        if (singletonObjects.containsKey(name)) {
            return singletonObjects.get(name);
        }
        // 如果没有,交给子类去创建
        Object bean = createBean(name);
        singletonObjects.put(name, bean);
        return bean;
    }

    // 留给子类扩展
    protected abstract Object createBean(String name);
}

实现类(不同扩展场景)

可以自己扩展不同的对象创建方式(硬编码、XML、注解、远程加载……)。

// 实现1:硬编码方式
public class SimpleContainer extends AbstractContainer {
    @Override
    protected Object createBean(String name) {
        if ("userService".equals(name)) {
            return new UserService();
        }
        throw new RuntimeException("No bean named " + name);
    }
}

// 实现2:配置文件方式
public class XmlContainer extends AbstractContainer {
    private Map<String, String> beanDefinitions = new HashMap<>();

    public XmlContainer() {
        beanDefinitions.put("userService", "com.example.UserService");
    }

    @Override
    protected Object createBean(String name) {
        try {
            String className = beanDefinitions.get(name);
            return Class.forName(className).newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

这样如果以后需要加上其他方式createBean,只需要继承这个抽象类实现createBean()方法就行了。

posted @ 2025-08-29 17:44  忧伤丶情语  阅读(6)  评论(0)    收藏  举报