抽象类和接口的应用场景?

抽象类(Abstract Class)

核心定位

  • 是一种继承体系的父类,用于抽取共有属性和部分通用方法,实现代码复用,并可以强制子类实现某些抽象方法。
  • 既可以有 成员变量,也可以有 方法实现(非抽象方法)。

适用场景

  1. 有明确的继承关系
    • 父类抽象出共性,子类扩展差异化功能。
    • 例:电商系统里 AbstractOrderService 定义通用的订单流程(校验 → 扣库存 → 支付)。
    • 部分步骤抽象出来让不同业务线(B2C、B2B)实现。
  2. 需要共用成员变量和已实现的方法
    • 例:AbstractReportGenerator 里定义 protected DataSource dataSource; 和一些公共数据格式化方法,子类直接复用。
  3. 部分方法需要默认实现
    • 父类提供默认实现,子类可选择重写。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class AbstractOrderService {
public void createOrder() {
checkParams();
lockStock();
pay();
}
protected abstract void checkParams();
protected abstract void lockStock();
protected void pay() {
System.out.println("默认支付逻辑");
}
}

接口(Interface)

核心定位

  • 是一种能力规范,关注能做什么,而不是:是什么。
  • 不能有实例字段(Java 8+ 接口可以有 default 方法和 static 方法,但依然不能持有实例状态)。

适用场景

  1. 多种不相关类共享相同行为
    • 例:Payable 接口定义 pay() 方法,用户、订单、账单都可以实现它,但它们之间不必有继承关系。
  2. 面向抽象编程、解耦依赖
    • 业务层依赖接口,而不是具体实现,方便替换(策略模式、工厂模式常用)。
    • 例:MessageSender 接口,微信、短信、邮件等不同实现类互换。
  3. 多实现(多继承能力)
    • Java 类不能多继承,但可以实现多个接口。
    • 例:一个类同时实现 RunnableComparable,既能被线程执行,又能排序。

代码示例:

1
2
3
4
5
6
7
8
9
public interface Payable {
void pay();
}

public class Order implements Payable {
public void pay() {
System.out.println("订单支付");
}
}

对比总结

对比点 抽象类 接口
本质 类(是一种是什么) 规范(是一种能做什么)
成员变量 可以有实例变量 不能有实例变量
方法实现 可以有已实现方法 Java 8 以前全是抽象方法
继承/实现数量 单继承 可多实现
设计目的 代码复用 + 统一规范 规范能力 + 解耦
使用前提 子类是父类的一种 实现类不必有关系

常见业务应用场景归纳

  • 抽象类:当你有一条明确的继承链、共享数据和部分实现时,例如:
    • 各种报表生成器共享数据连接和导出逻辑
    • 电商不同类型订单共用的下单流程
  • 接口:当你想定义某种能力或契约、让无关的类都能实现时,例如:
    • 不同支付渠道实现同一个 Payable 接口
    • 不同存储实现同一个 Cache 接口(Redis、内存、文件)