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()方法就行了。

浙公網安備 33010602011771號