抽象类应严格限定为定义契约和共性骨架,不得包含具体业务逻辑、硬编码操作或跨层职责;业务规则、数据访问、通知等需剥离至策略接口、服务类或组合组件;构造函数避免多服务注入,非抽象方法设为protected,包结构与可见性须配合职责收敛。

避免在Java抽象类中塞入大量具体业务逻辑,核心是守住“抽象”的边界——它只定义契约和共性骨架,不落地细节。
明确抽象类的定位:只管“做什么”,不管“怎么做”
抽象类不是为了复用业务代码而存在,而是为子类提供统一的行为轮廓和可复用的基础能力。一旦发现抽象类里出现硬编码的数据库操作、HTTP调用、状态判断分支(如 if (order.getStatus() == "PAID")),就说明它越界了。
- 把业务规则判断(如校验、状态流转)移出抽象类,交给策略接口或独立的服务类
- 把数据访问逻辑全部上提到具体实现类,或委托给Repository接口
- 抽象方法只声明签名,不提供默认实现;若需共用逻辑,应抽成
protected final工具方法,且该方法本身不含业务语义(例如formatTimestamp()可以,sendOrderConfirmedEmail()不行)
用组合替代“伪继承”式业务填充
常见误区:为复用一段订单创建逻辑,把createOrder()直接写进抽象父类,再让OnlineOrderService和OfflineOrderService去继承。这看似省事,实则强绑定了子类与特定流程。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 把可复用的流程封装成独立组件,比如
OrderCreator、IdGenerator、RetryPolicy - 在具体子类中以
private final字段持有这些组件,通过调用而非继承获得能力 - 这样既保持抽象类轻量,又让子类能自由替换或跳过某一步(比如线下订单不需要发短信通知)
警惕“抽象类变相成为上帝类”的信号
以下迹象表明抽象类正在失控:
- 构造函数里注入了多个具体服务(如
OrderRepository、SmsSender、RedisTemplate) - 类里同时存在
saveToDb()、notifyUser()、logAudit()等跨层职责 - 子类重写的方法极少,大部分逻辑都在父类里跑完
- 单元测试需要mock五六个协作对象才能跑通一个抽象类方法
此时应果断拆分:把业务动作提取为接口(如OrderPersistence、OrderNotifier),让抽象类仅依赖这些接口,具体实现由子类或外部注入。
包结构与可见性要配合职责收敛
抽象类不应暴露不该暴露的细节:
- 将抽象类及其配套接口放在同一功能包下(如
com.example.order.core),避免跨包引用具体实现 - 抽象类中的非抽象方法尽量设为
protected,禁止public暴露给无关调用方 - 禁止在抽象类中定义静态常量集合(如
STATUS_MAP)或工具方法(如parseJson()),这些应归属专门的工具类或领域对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










