模块模式是解耦行为复用与类型层级的关键手段,通过横向注入机制(如ruby include、java默认方法等)收敛共用参数,避免深继承链中冗余传递,并配合不可变配置对象提升类型安全与语义清晰度。

在高度抽象的领域模型继承体系中,模块模式不是用来替代继承的,而是用来解耦“行为复用”与“类型层级”的关键手段。它不直接参与继承链,却能显著减少参数在多层继承间冗余传递的负担。
明确模块模式在这里的角色
模块(如 Ruby 的 include、Java 的接口默认方法、C++ 的 mixin 模板、HarmonyOS 的 @Builder)本质是横向能力注入机制。它把本该分散在多个子类构造函数或方法签名里的共用参数,收敛到一个可配置、可组合的行为单元里——参数只传一次,被模块内部统一消费。
用模块收拢重复参数,避免层层透传
当领域模型存在深继承链(例如 FinancialProduct → Loan → Mortgage → AdjustableRateMortgage),每层若都需显式接收 currency, valuationDate, riskProfile 等上下文参数,会导致:
- 构造函数签名膨胀
- 子类初始化逻辑重复
- 修改参数类型需逐层调整
此时可用模块封装这些参数依赖:
- 定义一个
ValuationContext模块,接受currency: String,asOf: LocalDate作为初始化配置 - 在
FinancialProduct基类中include ValuationContext或通过组合持有其实例 - 所有子类自动获得
.getValuationRate()、.toBaseCurrency(amount)等方法,无需再声明或传递原始参数
这样,参数只在顶层注入一次,后续所有继承者共享同一上下文视图。
配合不可变配置对象,消除运行时参数歧义
避免把原始值(如字符串、数字)直接传入模块,而应封装为领域语义明确的不可变对象:
-
MoneyAmount(currency: Currency, value: BigDecimal) -
RiskAssessment(level: RiskLevel, source: String) -
TimePoint(businessDay: Boolean, zone: ZoneId)
模块接收这类对象后,内部方法可基于其语义做校验与转换,而不是反复解析字符串或做空值判断。这既提升类型安全性,也使参数意图一目了然。
在抽象工厂或构建器中预置模块实例
当领域对象通过工厂创建时,可将模块行为与配置一并绑定:
- 抽象工厂返回的
ProductFactory实例自带ValuationContext和ReportingModule - 具体产品子类在构造时只需调用
super(factory.context()),不再自行解析参数 - 工厂本身成为参数聚合点,天然承担“参数归集”职责
这种设计让继承体系专注表达“是什么”,而模块和工厂共同承担“怎么算、怎么报、怎么验”。
注意边界:模块不替代领域约束建模
模块适合封装跨层级的通用计算、格式化、审计等横切能力;但核心业务规则(如“抵押率不得超过80%”)仍应保留在对应聚合根或值对象中,通过领域事件或验证器触发,而非藏在模块方法里。否则会模糊模型责任,削弱可测试性与可追溯性。











