
本文讲解如何用 Java 的 Predicate 接口重构重复的 token 匹配逻辑,将条件判断抽象为可复用的高阶 match 方法,在保持可读性的同时真正践行 DRY(Don’t Repeat Yourself)原则。
本文讲解如何用 java 的 `predicate` 接口重构重复的 token 匹配逻辑,将条件判断抽象为可复用的高阶 `match` 方法,在保持可读性的同时真正践行 dry(don’t repeat yourself)原则。
在解析器或词法分析器开发中,频繁出现类似 match(ITokenType, int) 和 match(Class>, int) 这类语义高度一致、仅判断逻辑不同的方法——它们都执行三步操作:检查是否有有效 token → 获取目标 token → 根据特定条件判断是否匹配 → 成功则返回,否则返回 null。这种结构重复正是 DRY 原则被违反的典型信号。
直接合并为一个重载方法看似简单,但因判断逻辑本质不同(类型等值 vs 类型实例检查),硬编码会导致分支膨胀或类型擦除问题。更优雅的解法是将“判断逻辑”参数化:引入一个通用的 match(Predicate<token>, int)</token> 作为核心实现,再让两个原有方法作为语义清晰的门面(Facade),各自传入对应的 lambda 表达式:
public Token match(ITokenType expectedToken, int tokenNum) {
return match(t -> expectedToken == t.get_type(), tokenNum);
}
public Token match(Class> clazz, int tokenNum) {
return match(t -> clazz.isInstance(t.get_type()), tokenNum);
}
public Token match(Predicate<token> predicate, int tokenNum) {
if (hasToken(_currentTokenNum)) {
Token t = getToken(tokenNum);
if (predicate.test(t)) {
return t;
}
}
return null;
}</token>
✅ 优势说明:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 零重复逻辑:空校验、token 获取、返回路径全部收敛至单一方法;
- 开闭友好:新增匹配策略(如正则匹配、复合条件)只需新增一个门面方法,无需改动核心流程;
-
类型安全:
Predicate<token></token>明确约束输入类型,避免Object强转风险; -
延迟求值:
predicate.test(t)在getToken()之后执行,确保t非空且已就绪,符合原始语义。
⚠️ 注意事项:
- 不应为减少两处重复而牺牲可维护性。若两个方法长期共存、变更频率极低,且团队对 lambda 熟悉度不高,保留原貌亦是合理选择;
-
Predicate的语义应聚焦于 token 本身的类型判断,避免在 lambda 中嵌入副作用(如日志、状态修改),否则会破坏纯函数特性,降低可测试性; - 若未来
match内部逻辑扩展(如增加跳过空白、回溯支持),统一维护点的价值将显著提升——此时重构的 ROI(投资回报率)远高于初期成本。
总结而言,DRY 不是教条式的“消除所有重复”,而是识别有意义的抽象边界,并将变化点隔离为可配置行为。本例中,Predicate 正是那个恰到好处的抽象,它让代码既简洁又富有弹性,真正实现了“一次编写,多处受控复用”。










