Java 设计模式

最后更新: 2022-08-29 23:50:54 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

模式为反复出现的设计权衡命名。Java 语言特性可以实现模式,但 lambda 和依赖注入容器本身都不能替代设计决策。

创建型模式 #

当调用方不能依赖具体类型,或构造过程需要选择实现时,Factory 会集中管理创建过程。工厂可以隐藏有用的细节,但为每种产品都提供方法的工厂可能变成不必要的间接层。

java
interface Parser { Document parse(String text); }
final class Parsers {
    static Parser forFormat(Format format) { return format::parse; }
}

Builder 收集可选参数,并在生成不可变值之前验证跨字段不变量。当必需字段很少时,应使用构造函数或静态工厂;仅仅镜像 setter 的构建器会掩盖所需状态。在 Java 中,Prototype 通常用显式复制构造函数或 copyOf 工厂比 Cloneable 更清晰,因为后者的浅复制和继承语义难以安全扩展。

结构型模式 #

Adapter 将外部接口转换为应用拥有的契约。它避免供应商类型扩散到领域层,但需要维护转换逻辑。Decorator 在同一接口周围添加行为:

java
final class MeteredStore implements Store {
    private final Store delegate;
    public Value get(Key key) {
        metrics.recordAttempt();
        return delegate.get(key);
    }
}

当缓存、授权和指标等关注点独立变化时,组合装饰器优于组合子类。Java I/O 流就是经典示例。当需要简化有意设计得复杂的子系统,或对部分—整体树建模时,Facade 和 Composite 同样有用。

行为型模式 #

Strategy 在稳定接口之后选择算法。Java 可以通过接口实现、函数式接口的 lambda,或封闭策略集合的枚举常量来表达它:

java
enum Rounding {
    DOWN { BigDecimal apply(BigDecimal n) { return n.setScale(0, RoundingMode.DOWN); } },
    UP   { BigDecimal apply(BigDecimal n) { return n.setScale(0, RoundingMode.UP); } };
    abstract BigDecimal apply(BigDecimal n);
}

Observer 向监听器发布事件。应明确同步还是异步投递、顺序、失败隔离、背压和监听器所有权;否则观察者列表会变成隐藏的控制流。当 Command、Template Method、Iterator 和 State 模式能够在不引入大型条件语句的情况下明确变化时,它们仍然有用。

依赖注入从对象外部提供协作者。它可以连接工厂、策略、装饰器和观察者,但不会决定它们的边界。同样,record、密封类型、switch 和 lambda 可以减少样板代码;它们不会决定领域应由开放式多态还是封闭集合建模。

评论

在 GitHub 上阅读或评论(发表评论需要登录)