Java方法参数通过函数式接口实现策略动态注入,本质是面向接口编程与运行时多态结合,将“做什么”与“怎么做”分离,支持Lambda、方法引用等灵活实现,轻量解耦易扩展。

Java 中方法参数通过传递接口实现策略的动态注入,本质是利用“面向接口编程” + “运行时多态”,让调用方决定具体行为,而非在方法内部硬编码逻辑。这种方式轻量、解耦、易扩展,不需要继承体系或工厂类,核心在于把“做什么”(行为契约)和“怎么做”(具体实现)彻底分离。
用函数式接口定义统一行为契约
策略的起点是一个只声明一个抽象方法的接口——即函数式接口(加 @FunctionalInterface 更清晰)。它不关心谁实现,只约定“能接收什么、返回什么、做什么事”。比如:
- 支付策略:`@FunctionalInterface interface PaymentHandler { void pay(double amount); }`
- 通知方式:`@FunctionalInterface interface Notifier { void send(String msg); }`
-
数据校验:`@FunctionalInterface interface Validator
{ boolean valid(T input); }`
这些接口就是策略的“合同模板”,后续所有实现都必须遵守同一签名。
方法参数直接声明为该接口类型
业务方法不再依赖具体类,而是接收接口作为参数。这样方法本身不绑定任何实现,只执行契约规定的动作:
立即学习“Java免费学习笔记(深入)”;
- `public void processOrder(Order order, PaymentHandler handler) { handler.pay(order.getTotal()); }`
- `public void alert(String content, Notifier notifier) { notifier.send(content); }`
调用时传入任意符合接口定义的对象——可以是传统实现类的实例,也可以是 Lambda 表达式,甚至方法引用。例如:
- `processOrder(order, amount -> System.out.println("Alipay: ¥" + amount));`
- `alert("Low stock", emailService::send);`
- `alert("Urgent", s -> smsClient.send(s, "+86139..."));`
用 Lambda 实现即用即抛的策略注入
Lambda 是最自然的动态策略载体。它省去类定义、编译、维护成本,把策略逻辑直接写在调用点附近,语义清晰且作用域可控:
- 替代 if-else 分支:`discount.apply(price)` 可由 `UserLevel.VIP ? p -> p * 0.8 : p -> p * 0.95` 动态决定
- 组合多个策略:`Function
clean = s -> s.trim().toLowerCase(); Function escape = s -> s.replace(" - 临时定制回调:`list.forEach(item -> log.info("Processed: {}", item.getId()));`
这种写法没有类加载开销,不污染全局命名空间,特别适合配置化、规则化、一次性使用的场景。
结合 Map 或配置中心做策略路由
当策略种类较多、需按条件选择时,可将 Lambda 预先注册进 Map,键为策略标识(如枚举、字符串),值为对应行为:
- `Map
> rules = Map.of("VIP", p -> p * 0.8, "GOLD", p -> p * 0.9, "BASIC", p -> p);` - 调用时:`double finalPrice = rules.get(user.getTier()).apply(originalPrice);`
这个 Map 可来自配置文件、数据库或运行时动态更新,真正实现“策略可插拔、逻辑不重启”。


















