核心思路是用抽象代替具体、契约代替实现,通过接口参数、函数式接口、专用参数对象和职责拆分提升代码可维护性与复用性。

核心思路是:用抽象代替具体,用契约代替实现,让方法不绑定特定类型或行为细节。
用接口或抽象类作为参数类型
避免直接传入具体实现类,改用其上层接口。这样调用方只需满足接口约定,无需关心内部怎么实现。
- 比如业务方法接收 Logger 接口而非 FileLogger 或 ConsoleLogger 实例
- 数据库操作方法接收 DataSource 而非 HikariDataSource,后续换成 Druid 或测试用的 H2 数据源都不需改方法签名
- 关键点:接口定义的是“能做什么”,不是“是谁做的”
用函数式接口传递行为逻辑
把可变的处理逻辑抽成参数,而不是在方法内部硬编码判断或调用固定类。
- 例如过滤集合时,传入 Predicate
而非写死 if-else 判断条件 - 格式化输出时,传入 Function
,而不是在方法里写死 toString() 或 JSON 序列化逻辑 - 好处是:同一方法可复用于不同场景,且单元测试时可轻松注入模拟逻辑
避免传递原始数据结构或配置对象
不要把 Map、JSONObject 或自定义 DTO 当作“万能参数”传入,这会隐式绑定调用方的数据组织方式。
- 传 Map 容易导致方法内出现大量 get("xxx") 和类型强转,一旦 key 名或结构变,调用方和被调方都得改
- 推荐封装为专用参数对象(如 SearchCriteria),字段明确、不可变、带校验
- 这样既清晰表达了意图,又隔离了数据结构变化的影响范围
慎用布尔或枚举控制分支
靠 flag 参数切换行为,本质是把多个职责塞进一个方法,增加理解成本和维护风险。
- 像 process(order, true) 和 process(order, false) 很难一眼看出差异
- 更优做法:拆成 processForNormalOrder() 和 processForUrgentOrder(),或用策略接口统一入口
- 如果必须保留开关,至少配合 Java 8+ 的 Optional 或 Builder 模式,让调用更显式
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











