类图中基于组合或继承扩展对象属性的设计困惑
针对算法类设计的方案评估与建议
原设计核心问题
原设计中Engine、DefaultAlgorithm、DecoratedAlgorithm均关联Algorithm属性,导致属性嵌套访问繁琐,且与“嵌套属性不适用于持久化”的需求直接冲突,这确实是需要解决的问题。
备选方案分析
方案1:让三类继承Algorithm
- 优势:
- 彻底消除属性嵌套,访问属性无需链式调用(如
defaultAlgorithm.property而非defaultAlgorithm.algorithm.property),代码简洁直观; - 生成Default/DecoratedAlgorithm时,继承的属性可直接复用,无需额外传递或复制;
- 持久化时能直接映射类自身属性,完全适配需求。
- 彻底消除属性嵌套,访问属性无需链式调用(如
- 隐患:
- 违反“组合优于继承”原则,若后续Algorithm的属性或行为变更,所有子类都会被迫同步修改,维护成本随系统迭代上升;
- 需验证Engine的语义是否适合继承Algorithm:Engine是生成器,本质上是否属于Algorithm的子类?如果逻辑不匹配,继承会导致类层次语义混乱,后续扩展易出问题。
方案2:在三类中重复添加Algorithm的属性
- 优势:
- 避免继承带来的语义矛盾,每个类的属性独立,逻辑边界清晰;
- 持久化时直接处理自身属性,无嵌套障碍。
- 隐患:
- 严重的代码冗余,相同属性需在多个类中重复定义和维护,后续修改Algorithm属性时,要同步修改所有类,极易遗漏出错;
- 生成对象时需手动复制属性值,增加代码量和出错概率。
折中建议
针对小型系统的场景,可根据实际语义选择更平衡的方案:
- 若Engine逻辑上属于Algorithm子类:优先用方案1,小型系统复杂度低,继承带来的维护问题短期内不会凸显,能快速解决当前核心痛点;
- 若Engine不属于Algorithm子类:
- 让DefaultAlgorithm和DecoratedAlgorithm继承Algorithm,解决它们的持久化和属性访问问题;
- Engine通过组合持有Algorithm实例,同时在Engine中添加委托方法直接暴露Algorithm的属性(如
getProperty() { return this.algorithm.getProperty(); }),既避免嵌套访问,又符合逻辑语义;
- 更优雅的进阶方案:把Algorithm的属性抽成独立的
AlgorithmMetadataDTO,让三类都持有该DTO实例,并在类中添加委托方法访问DTO属性。这样既避免重复代码,又遵循组合原则,持久化时可将DTO属性映射到对应表字段,或作为嵌入式对象处理(若ORM支持)。
内容的提问来源于stack exchange,提问作者Jeppe Christensen
相关产品推荐
相关产品推荐

