SAP-ABAP:继承深度优化:避免层级过深的设计原则与组合替代继承的实践方案


ABAP核心进阶篇(120篇):继承、多态与接口(12篇)

第十篇:继承深度优化:避免层级过深的设计原则与组合替代继承的实践方案

博客标题:《继承深度优化:避免层级过深的设计原则与组合替代继承的实践方案》

博客简介:分析继承层级过深导致的代码耦合、迭代困难问题,讲解"组合优于继承"的设计思路,结合实际业务场景演示如何通过类的组合+接口实现替代深层继承结构,大幅提升代码的可维护性与扩展性。

📖 写在前面

在ABAP面向对象开发中,继承是实现代码复用的重要手段。但在实际项目中,我们经常会遇到继承层级过深的问题:
#mermaid-svg-NKrxQKQG6lI9knnx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NKrxQKQG6lI9knnx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NKrxQKQG6lI9knnx .error-icon{fill:#552222;}#mermaid-svg-NKrxQKQG6lI9knnx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NKrxQKQG6lI9knnx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NKrxQKQG6lI9knnx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NKrxQKQG6lI9knnx .marker.cross{stroke:#333333;}#mermaid-svg-NKrxQKQG6lI9knnx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NKrxQKQG6lI9knnx p{margin:0;}#mermaid-svg-NKrxQKQG6lI9knnx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NKrxQKQG6lI9knnx .cluster-label text{fill:#333;}#mermaid-svg-NKrxQKQG6lI9knnx .cluster-label span{color:#333;}#mermaid-svg-NKrxQKQG6lI9knnx .cluster-label span p{background-color:transparent;}#mermaid-svg-NKrxQKQG6lI9knnx .label text,#mermaid-svg-NKrxQKQG6lI9knnx span{fill:#333;color:#333;}#mermaid-svg-NKrxQKQG6lI9knnx .node rect,#mermaid-svg-NKrxQKQG6lI9knnx .node circle,#mermaid-svg-NKrxQKQG6lI9knnx .node ellipse,#mermaid-svg-NKrxQKQG6lI9knnx .node polygon,#mermaid-svg-NKrxQKQG6lI9knnx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NKrxQKQG6lI9knnx .rough-node .label text,#mermaid-svg-NKrxQKQG6lI9knnx .node .label text,#mermaid-svg-NKrxQKQG6lI9knnx .image-shape .label,#mermaid-svg-NKrxQKQG6lI9knnx .icon-shape .label{text-anchor:middle;}#mermaid-svg-NKrxQKQG6lI9knnx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NKrxQKQG6lI9knnx .rough-node .label,#mermaid-svg-NKrxQKQG6lI9knnx .node .label,#mermaid-svg-NKrxQKQG6lI9knnx .image-shape .label,#mermaid-svg-NKrxQKQG6lI9knnx .icon-shape .label{text-align:center;}#mermaid-svg-NKrxQKQG6lI9knnx .node.clickable{cursor:pointer;}#mermaid-svg-NKrxQKQG6lI9knnx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NKrxQKQG6lI9knnx .arrowheadPath{fill:#333333;}#mermaid-svg-NKrxQKQG6lI9knnx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NKrxQKQG6lI9knnx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NKrxQKQG6lI9knnx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NKrxQKQG6lI9knnx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NKrxQKQG6lI9knnx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NKrxQKQG6lI9knnx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NKrxQKQG6lI9knnx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NKrxQKQG6lI9knnx .cluster text{fill:#333;}#mermaid-svg-NKrxQKQG6lI9knnx .cluster span{color:#333;}#mermaid-svg-NKrxQKQG6lI9knnx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NKrxQKQG6lI9knnx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NKrxQKQG6lI9knnx rect.text{fill:none;stroke-width:0;}#mermaid-svg-NKrxQKQG6lI9knnx .icon-shape,#mermaid-svg-NKrxQKQG6lI9knnx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NKrxQKQG6lI9knnx .icon-shape p,#mermaid-svg-NKrxQKQG6lI9knnx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NKrxQKQG6lI9knnx .icon-shape .label rect,#mermaid-svg-NKrxQKQG6lI9knnx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NKrxQKQG6lI9knnx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NKrxQKQG6lI9knnx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NKrxQKQG6lI9knnx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🔴 过深的继承链
第1层:zcl_object
第2层:zcl_business_object
第3层:zcl_document
第4层:zcl_order
第5层:zcl_purchase_order
第6层:zcl_standard_po

深层继承的典型问题

问题 表现 后果
🔴 逻辑追踪困难 方法实现分散在6层父类中 调试耗时,理解成本高
🔴 修改影响面大 父类修改影响所有子类 修改风险极高
🔴 继承"遗产"过多 子类继承了不需要的方法 代码臃肿,职责不清
🔴 扩展困难 业务变更需调整继承结构 违反开闭原则

本文将分析继承层级过深的问题,讲解 "组合优于继承" 的设计思路,并通过实际业务场景演示如何通过组合替代继承,大幅提升代码的可维护性与扩展性。

一、继承层级过深的问题分析

1.1 一个真实的问题代码示例

abap 复制代码
" ================================================================
" ❌ 继承层级过深的示例(6层继承)
" ================================================================

" 第1层:基础对象
CLASS zcl_object DEFINITION.
  PUBLIC SECTION.
    METHODS: initialize.
ENDCLASS.

" 第2层:业务对象
CLASS zcl_business_object DEFINITION INHERITING FROM zcl_object.
  PUBLIC SECTION.
    METHODS: validate.
ENDCLASS.

" 第3层:单据对象
CLASS zcl_document DEFINITION INHERITING FROM zcl_business_object.
  PUBLIC SECTION.
    METHODS: save.
ENDCLASS.

" 第4层:订单对象
CLASS zcl_order DEFINITION INHERITING FROM zcl_document.
  PUBLIC SECTION.
    METHODS: create.
ENDCLASS.

" 第5层:采购订单
CLASS zcl_purchase_order DEFINITION INHERITING FROM zcl_order.
  PUBLIC SECTION.
    METHODS: settle.
ENDCLASS.

" 第6层:标准采购订单
CLASS zcl_standard_po DEFINITION INHERITING FROM zcl_purchase_order.
  PUBLIC SECTION.
    METHODS: calculate_amount.
ENDCLASS.

" ================================================================
" ❌ 调用时,开发人员需要了解整个继承链
" ================================================================
DATA(lo_po) = NEW zcl_standard_po( ).
lo_po->initialize( ).          " 来自第1层(6层之上)
lo_po->validate( ).            " 来自第2层(5层之上)
lo_po->save( ).                " 来自第3层(4层之上)
lo_po->create( ).              " 来自第4层(3层之上)
lo_po->settle( ).              " 来自第5层(2层之上)
lo_po->calculate_amount( ).    " 来自第6层(自身)

1.2 深层继承的五大问题

#mermaid-svg-XBgWZhEyyLiuZF8D{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XBgWZhEyyLiuZF8D .error-icon{fill:#552222;}#mermaid-svg-XBgWZhEyyLiuZF8D .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XBgWZhEyyLiuZF8D .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XBgWZhEyyLiuZF8D .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XBgWZhEyyLiuZF8D .marker.cross{stroke:#333333;}#mermaid-svg-XBgWZhEyyLiuZF8D svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XBgWZhEyyLiuZF8D p{margin:0;}#mermaid-svg-XBgWZhEyyLiuZF8D .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster-label text{fill:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster-label span{color:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster-label span p{background-color:transparent;}#mermaid-svg-XBgWZhEyyLiuZF8D .label text,#mermaid-svg-XBgWZhEyyLiuZF8D span{fill:#333;color:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D .node rect,#mermaid-svg-XBgWZhEyyLiuZF8D .node circle,#mermaid-svg-XBgWZhEyyLiuZF8D .node ellipse,#mermaid-svg-XBgWZhEyyLiuZF8D .node polygon,#mermaid-svg-XBgWZhEyyLiuZF8D .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XBgWZhEyyLiuZF8D .rough-node .label text,#mermaid-svg-XBgWZhEyyLiuZF8D .node .label text,#mermaid-svg-XBgWZhEyyLiuZF8D .image-shape .label,#mermaid-svg-XBgWZhEyyLiuZF8D .icon-shape .label{text-anchor:middle;}#mermaid-svg-XBgWZhEyyLiuZF8D .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XBgWZhEyyLiuZF8D .rough-node .label,#mermaid-svg-XBgWZhEyyLiuZF8D .node .label,#mermaid-svg-XBgWZhEyyLiuZF8D .image-shape .label,#mermaid-svg-XBgWZhEyyLiuZF8D .icon-shape .label{text-align:center;}#mermaid-svg-XBgWZhEyyLiuZF8D .node.clickable{cursor:pointer;}#mermaid-svg-XBgWZhEyyLiuZF8D .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XBgWZhEyyLiuZF8D .arrowheadPath{fill:#333333;}#mermaid-svg-XBgWZhEyyLiuZF8D .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XBgWZhEyyLiuZF8D .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XBgWZhEyyLiuZF8D .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XBgWZhEyyLiuZF8D .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XBgWZhEyyLiuZF8D .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XBgWZhEyyLiuZF8D .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster text{fill:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D .cluster span{color:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XBgWZhEyyLiuZF8D .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XBgWZhEyyLiuZF8D rect.text{fill:none;stroke-width:0;}#mermaid-svg-XBgWZhEyyLiuZF8D .icon-shape,#mermaid-svg-XBgWZhEyyLiuZF8D .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XBgWZhEyyLiuZF8D .icon-shape p,#mermaid-svg-XBgWZhEyyLiuZF8D .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XBgWZhEyyLiuZF8D .icon-shape .label rect,#mermaid-svg-XBgWZhEyyLiuZF8D .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XBgWZhEyyLiuZF8D .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XBgWZhEyyLiuZF8D .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XBgWZhEyyLiuZF8D :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ❌ 深层继承问题
代码耦合
逻辑追踪困难
职责不清
扩展性差
测试困难
修改父类影响所有子类
需要逐层查看父类代码
各层职责边界模糊
新增功能需修改继承结构
需测试整个继承链

二、组合优于继承的设计原则

2.1 什么是组合?

组合(Composition) 是将多个类的实例作为属性组合在一起,通过调用组合对象的方法来实现功能。
#mermaid-svg-S9pLlZQWIsc80FmR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-S9pLlZQWIsc80FmR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S9pLlZQWIsc80FmR .error-icon{fill:#552222;}#mermaid-svg-S9pLlZQWIsc80FmR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S9pLlZQWIsc80FmR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S9pLlZQWIsc80FmR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S9pLlZQWIsc80FmR .marker.cross{stroke:#333333;}#mermaid-svg-S9pLlZQWIsc80FmR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S9pLlZQWIsc80FmR p{margin:0;}#mermaid-svg-S9pLlZQWIsc80FmR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-S9pLlZQWIsc80FmR .cluster-label text{fill:#333;}#mermaid-svg-S9pLlZQWIsc80FmR .cluster-label span{color:#333;}#mermaid-svg-S9pLlZQWIsc80FmR .cluster-label span p{background-color:transparent;}#mermaid-svg-S9pLlZQWIsc80FmR .label text,#mermaid-svg-S9pLlZQWIsc80FmR span{fill:#333;color:#333;}#mermaid-svg-S9pLlZQWIsc80FmR .node rect,#mermaid-svg-S9pLlZQWIsc80FmR .node circle,#mermaid-svg-S9pLlZQWIsc80FmR .node ellipse,#mermaid-svg-S9pLlZQWIsc80FmR .node polygon,#mermaid-svg-S9pLlZQWIsc80FmR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S9pLlZQWIsc80FmR .rough-node .label text,#mermaid-svg-S9pLlZQWIsc80FmR .node .label text,#mermaid-svg-S9pLlZQWIsc80FmR .image-shape .label,#mermaid-svg-S9pLlZQWIsc80FmR .icon-shape .label{text-anchor:middle;}#mermaid-svg-S9pLlZQWIsc80FmR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-S9pLlZQWIsc80FmR .rough-node .label,#mermaid-svg-S9pLlZQWIsc80FmR .node .label,#mermaid-svg-S9pLlZQWIsc80FmR .image-shape .label,#mermaid-svg-S9pLlZQWIsc80FmR .icon-shape .label{text-align:center;}#mermaid-svg-S9pLlZQWIsc80FmR .node.clickable{cursor:pointer;}#mermaid-svg-S9pLlZQWIsc80FmR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-S9pLlZQWIsc80FmR .arrowheadPath{fill:#333333;}#mermaid-svg-S9pLlZQWIsc80FmR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-S9pLlZQWIsc80FmR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-S9pLlZQWIsc80FmR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S9pLlZQWIsc80FmR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-S9pLlZQWIsc80FmR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S9pLlZQWIsc80FmR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-S9pLlZQWIsc80FmR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S9pLlZQWIsc80FmR .cluster text{fill:#333;}#mermaid-svg-S9pLlZQWIsc80FmR .cluster span{color:#333;}#mermaid-svg-S9pLlZQWIsc80FmR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-S9pLlZQWIsc80FmR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S9pLlZQWIsc80FmR rect.text{fill:none;stroke-width:0;}#mermaid-svg-S9pLlZQWIsc80FmR .icon-shape,#mermaid-svg-S9pLlZQWIsc80FmR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S9pLlZQWIsc80FmR .icon-shape p,#mermaid-svg-S9pLlZQWIsc80FmR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-S9pLlZQWIsc80FmR .icon-shape .label rect,#mermaid-svg-S9pLlZQWIsc80FmR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S9pLlZQWIsc80FmR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S9pLlZQWIsc80FmR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S9pLlZQWIsc80FmR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ✅ 组合模式
主类
验证组件
保存组件
计算组件
审批组件

2.2 组合 vs 继承:全方位对比

维度 🔴 继承 🟢 组合
关系 "is-a"(是一个) "has-a"(有一个)
耦合度 🔴 高(子类依赖父类) 🟢 低(组件独立封装)
灵活性 🔴 差(固定继承结构) 🟢 好(灵活组合组件)
扩展性 🔴 差(修改父类影响所有子类) 🟢 好(新增组件不影响现有代码)
职责 🔴 可能包含多个职责 🟢 每个组件职责单一
测试 🔴 需测试整个继承链 🟢 只需测试单个组件

2.3 组合的四种实现模式

模式 说明 示例
接口组合 通过接口引用组合对象 DATA: validator TYPE REF TO zif_validatable
构造函数注入 在构造函数中传入依赖 NEW zcl_order( io_validator = ... )
Setter注入 通过SET方法注入依赖 lo_order->set_validator( ... )
工厂组合 通过工厂创建完整组合对象 zcl_order_factory=>create( )

三、组合替代继承的实践方案

3.1 四步法重构流程

#mermaid-svg-IJstZapVEjKRyKFg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IJstZapVEjKRyKFg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IJstZapVEjKRyKFg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IJstZapVEjKRyKFg .error-icon{fill:#552222;}#mermaid-svg-IJstZapVEjKRyKFg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IJstZapVEjKRyKFg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IJstZapVEjKRyKFg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IJstZapVEjKRyKFg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IJstZapVEjKRyKFg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IJstZapVEjKRyKFg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IJstZapVEjKRyKFg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IJstZapVEjKRyKFg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IJstZapVEjKRyKFg .marker.cross{stroke:#333333;}#mermaid-svg-IJstZapVEjKRyKFg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IJstZapVEjKRyKFg p{margin:0;}#mermaid-svg-IJstZapVEjKRyKFg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IJstZapVEjKRyKFg .cluster-label text{fill:#333;}#mermaid-svg-IJstZapVEjKRyKFg .cluster-label span{color:#333;}#mermaid-svg-IJstZapVEjKRyKFg .cluster-label span p{background-color:transparent;}#mermaid-svg-IJstZapVEjKRyKFg .label text,#mermaid-svg-IJstZapVEjKRyKFg span{fill:#333;color:#333;}#mermaid-svg-IJstZapVEjKRyKFg .node rect,#mermaid-svg-IJstZapVEjKRyKFg .node circle,#mermaid-svg-IJstZapVEjKRyKFg .node ellipse,#mermaid-svg-IJstZapVEjKRyKFg .node polygon,#mermaid-svg-IJstZapVEjKRyKFg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IJstZapVEjKRyKFg .rough-node .label text,#mermaid-svg-IJstZapVEjKRyKFg .node .label text,#mermaid-svg-IJstZapVEjKRyKFg .image-shape .label,#mermaid-svg-IJstZapVEjKRyKFg .icon-shape .label{text-anchor:middle;}#mermaid-svg-IJstZapVEjKRyKFg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IJstZapVEjKRyKFg .rough-node .label,#mermaid-svg-IJstZapVEjKRyKFg .node .label,#mermaid-svg-IJstZapVEjKRyKFg .image-shape .label,#mermaid-svg-IJstZapVEjKRyKFg .icon-shape .label{text-align:center;}#mermaid-svg-IJstZapVEjKRyKFg .node.clickable{cursor:pointer;}#mermaid-svg-IJstZapVEjKRyKFg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IJstZapVEjKRyKFg .arrowheadPath{fill:#333333;}#mermaid-svg-IJstZapVEjKRyKFg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IJstZapVEjKRyKFg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IJstZapVEjKRyKFg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IJstZapVEjKRyKFg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IJstZapVEjKRyKFg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IJstZapVEjKRyKFg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IJstZapVEjKRyKFg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IJstZapVEjKRyKFg .cluster text{fill:#333;}#mermaid-svg-IJstZapVEjKRyKFg .cluster span{color:#333;}#mermaid-svg-IJstZapVEjKRyKFg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IJstZapVEjKRyKFg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IJstZapVEjKRyKFg rect.text{fill:none;stroke-width:0;}#mermaid-svg-IJstZapVEjKRyKFg .icon-shape,#mermaid-svg-IJstZapVEjKRyKFg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IJstZapVEjKRyKFg .icon-shape p,#mermaid-svg-IJstZapVEjKRyKFg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IJstZapVEjKRyKFg .icon-shape .label rect,#mermaid-svg-IJstZapVEjKRyKFg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IJstZapVEjKRyKFg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IJstZapVEjKRyKFg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IJstZapVEjKRyKFg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 识别可组合的能力
② 定义能力接口
③ 实现能力类
④ 组合能力到业务类

3.2 步骤一:识别可组合的能力

#mermaid-svg-6x52uBDHRA6OJWkH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6x52uBDHRA6OJWkH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6x52uBDHRA6OJWkH .error-icon{fill:#552222;}#mermaid-svg-6x52uBDHRA6OJWkH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6x52uBDHRA6OJWkH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6x52uBDHRA6OJWkH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6x52uBDHRA6OJWkH .marker.cross{stroke:#333333;}#mermaid-svg-6x52uBDHRA6OJWkH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6x52uBDHRA6OJWkH p{margin:0;}#mermaid-svg-6x52uBDHRA6OJWkH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6x52uBDHRA6OJWkH .cluster-label text{fill:#333;}#mermaid-svg-6x52uBDHRA6OJWkH .cluster-label span{color:#333;}#mermaid-svg-6x52uBDHRA6OJWkH .cluster-label span p{background-color:transparent;}#mermaid-svg-6x52uBDHRA6OJWkH .label text,#mermaid-svg-6x52uBDHRA6OJWkH span{fill:#333;color:#333;}#mermaid-svg-6x52uBDHRA6OJWkH .node rect,#mermaid-svg-6x52uBDHRA6OJWkH .node circle,#mermaid-svg-6x52uBDHRA6OJWkH .node ellipse,#mermaid-svg-6x52uBDHRA6OJWkH .node polygon,#mermaid-svg-6x52uBDHRA6OJWkH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6x52uBDHRA6OJWkH .rough-node .label text,#mermaid-svg-6x52uBDHRA6OJWkH .node .label text,#mermaid-svg-6x52uBDHRA6OJWkH .image-shape .label,#mermaid-svg-6x52uBDHRA6OJWkH .icon-shape .label{text-anchor:middle;}#mermaid-svg-6x52uBDHRA6OJWkH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6x52uBDHRA6OJWkH .rough-node .label,#mermaid-svg-6x52uBDHRA6OJWkH .node .label,#mermaid-svg-6x52uBDHRA6OJWkH .image-shape .label,#mermaid-svg-6x52uBDHRA6OJWkH .icon-shape .label{text-align:center;}#mermaid-svg-6x52uBDHRA6OJWkH .node.clickable{cursor:pointer;}#mermaid-svg-6x52uBDHRA6OJWkH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6x52uBDHRA6OJWkH .arrowheadPath{fill:#333333;}#mermaid-svg-6x52uBDHRA6OJWkH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6x52uBDHRA6OJWkH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6x52uBDHRA6OJWkH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6x52uBDHRA6OJWkH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6x52uBDHRA6OJWkH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6x52uBDHRA6OJWkH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6x52uBDHRA6OJWkH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6x52uBDHRA6OJWkH .cluster text{fill:#333;}#mermaid-svg-6x52uBDHRA6OJWkH .cluster span{color:#333;}#mermaid-svg-6x52uBDHRA6OJWkH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6x52uBDHRA6OJWkH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6x52uBDHRA6OJWkH rect.text{fill:none;stroke-width:0;}#mermaid-svg-6x52uBDHRA6OJWkH .icon-shape,#mermaid-svg-6x52uBDHRA6OJWkH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6x52uBDHRA6OJWkH .icon-shape p,#mermaid-svg-6x52uBDHRA6OJWkH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6x52uBDHRA6OJWkH .icon-shape .label rect,#mermaid-svg-6x52uBDHRA6OJWkH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6x52uBDHRA6OJWkH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6x52uBDHRA6OJWkH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6x52uBDHRA6OJWkH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🟢 提取为独立能力
🔴 原继承链中的方法
validate()
save()
calculate()
approve()
settle()
验证能力
保存能力
计算能力
审批能力
结算能力

3.3 步骤二:定义能力接口

abap 复制代码
" ================================================================
" ✅ 每个接口只定义一种能力(单一职责原则)
" ================================================================

INTERFACE zif_validatable.
  METHODS: validate RETURNING VALUE(rv_valid) TYPE abap_bool.
ENDINTERFACE.

INTERFACE zif_savable.
  METHODS: save.
ENDINTERFACE.

INTERFACE zif_calculable.
  METHODS: calculate
    IMPORTING iv_amount TYPE netwr
    RETURNING VALUE(rv_result) TYPE netwr.
ENDINTERFACE.

INTERFACE zif_approvable.
  METHODS: approve
    IMPORTING iv_approver TYPE sy-uname.
ENDINTERFACE.

INTERFACE zif_settlement.
  METHODS: settle RETURNING VALUE(rv_success) TYPE abap_bool.
ENDINTERFACE.

3.4 步骤三:实现能力类

abap 复制代码
" ================================================================
" ✅ 每个能力类独立实现一种能力
" ================================================================

" 验证能力
CLASS zcl_po_validator DEFINITION.
  PUBLIC SECTION.
    INTERFACES: zif_validatable.
ENDCLASS.

CLASS zcl_po_validator IMPLEMENTATION.
  METHOD zif_validatable~validate.
    WRITE: / '✅ 采购订单验证通过'.
    rv_valid = abap_true.
  ENDMETHOD.
ENDCLASS.

" 保存能力
CLASS zcl_po_saver DEFINITION.
  PUBLIC SECTION.
    INTERFACES: zif_savable.
ENDCLASS.

CLASS zcl_po_saver IMPLEMENTATION.
  METHOD zif_savable~save.
    WRITE: / '💾 采购订单已保存'.
  ENDMETHOD.
ENDCLASS.

" 计算能力
CLASS zcl_po_calculator DEFINITION.
  PUBLIC SECTION.
    INTERFACES: zif_calculable.
ENDCLASS.

CLASS zcl_po_calculator IMPLEMENTATION.
  METHOD zif_calculable~calculate.
    WRITE: / '🧮 采购订单计算'.
    rv_result = iv_amount * 1.1.   " 含10%附加费
  ENDMETHOD.
ENDCLASS.

3.5 步骤四:组合能力到业务类

abap 复制代码
" ================================================================
" ✅ 通过组合实现业务类("has-a"关系)
" ================================================================
CLASS zcl_purchase_order DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor.
    METHODS: process.
  PRIVATE SECTION.
    DATA: validator  TYPE REF TO zif_validatable,
          saver      TYPE REF TO zif_savable,
          calculator TYPE REF TO zif_calculable,
          approver   TYPE REF TO zif_approvable,
          settlement TYPE REF TO zif_settlement.
ENDCLASS.

CLASS zcl_purchase_order IMPLEMENTATION.
  METHOD constructor.
    validator  = NEW zcl_po_validator( ).
    saver      = NEW zcl_po_saver( ).
    calculator = NEW zcl_po_calculator( ).
    approver   = NEW zcl_po_approver( ).
    settlement = NEW zcl_po_settlement( ).
  ENDMETHOD.

  METHOD process.
    " 🎯 按需调用组合的能力
    IF validator->validate( ) = abap_true.
      DATA(lv_total) = calculator->calculate( 10000 ).
      approver->approve( 'USER01' ).
      settlement->settle( ).
      saver->save( ).
      WRITE: / '📋 总金额:', lv_total.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

四、组合替代继承的实际业务场景

4.1 业务需求

企业需要四种采购订单类型,每种需要不同的能力组合:

订单类型 验证 保存 计算 审批 结算
标准采购订单
紧急采购订单
框架采购订单
服务采购订单

4.2 传统继承方案的局限

#mermaid-svg-eaD1ezVbY3YdXo66{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eaD1ezVbY3YdXo66 .error-icon{fill:#552222;}#mermaid-svg-eaD1ezVbY3YdXo66 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eaD1ezVbY3YdXo66 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eaD1ezVbY3YdXo66 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eaD1ezVbY3YdXo66 .marker.cross{stroke:#333333;}#mermaid-svg-eaD1ezVbY3YdXo66 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eaD1ezVbY3YdXo66 p{margin:0;}#mermaid-svg-eaD1ezVbY3YdXo66 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster-label text{fill:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster-label span{color:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster-label span p{background-color:transparent;}#mermaid-svg-eaD1ezVbY3YdXo66 .label text,#mermaid-svg-eaD1ezVbY3YdXo66 span{fill:#333;color:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 .node rect,#mermaid-svg-eaD1ezVbY3YdXo66 .node circle,#mermaid-svg-eaD1ezVbY3YdXo66 .node ellipse,#mermaid-svg-eaD1ezVbY3YdXo66 .node polygon,#mermaid-svg-eaD1ezVbY3YdXo66 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eaD1ezVbY3YdXo66 .rough-node .label text,#mermaid-svg-eaD1ezVbY3YdXo66 .node .label text,#mermaid-svg-eaD1ezVbY3YdXo66 .image-shape .label,#mermaid-svg-eaD1ezVbY3YdXo66 .icon-shape .label{text-anchor:middle;}#mermaid-svg-eaD1ezVbY3YdXo66 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eaD1ezVbY3YdXo66 .rough-node .label,#mermaid-svg-eaD1ezVbY3YdXo66 .node .label,#mermaid-svg-eaD1ezVbY3YdXo66 .image-shape .label,#mermaid-svg-eaD1ezVbY3YdXo66 .icon-shape .label{text-align:center;}#mermaid-svg-eaD1ezVbY3YdXo66 .node.clickable{cursor:pointer;}#mermaid-svg-eaD1ezVbY3YdXo66 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eaD1ezVbY3YdXo66 .arrowheadPath{fill:#333333;}#mermaid-svg-eaD1ezVbY3YdXo66 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eaD1ezVbY3YdXo66 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eaD1ezVbY3YdXo66 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eaD1ezVbY3YdXo66 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eaD1ezVbY3YdXo66 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eaD1ezVbY3YdXo66 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster text{fill:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 .cluster span{color:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eaD1ezVbY3YdXo66 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eaD1ezVbY3YdXo66 rect.text{fill:none;stroke-width:0;}#mermaid-svg-eaD1ezVbY3YdXo66 .icon-shape,#mermaid-svg-eaD1ezVbY3YdXo66 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eaD1ezVbY3YdXo66 .icon-shape p,#mermaid-svg-eaD1ezVbY3YdXo66 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eaD1ezVbY3YdXo66 .icon-shape .label rect,#mermaid-svg-eaD1ezVbY3YdXo66 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eaD1ezVbY3YdXo66 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eaD1ezVbY3YdXo66 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eaD1ezVbY3YdXo66 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🔴 继承方案(不灵活)
基础订单类
采购订单类
标准采购订单
紧急采购订单
框架采购订单
服务采购订单
⚠️ 新增能力组合时,需调整继承结构

4.3 组合方案的灵活性

#mermaid-svg-1Y3BNhXzNzONqINP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1Y3BNhXzNzONqINP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1Y3BNhXzNzONqINP .error-icon{fill:#552222;}#mermaid-svg-1Y3BNhXzNzONqINP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1Y3BNhXzNzONqINP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1Y3BNhXzNzONqINP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1Y3BNhXzNzONqINP .marker.cross{stroke:#333333;}#mermaid-svg-1Y3BNhXzNzONqINP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1Y3BNhXzNzONqINP p{margin:0;}#mermaid-svg-1Y3BNhXzNzONqINP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1Y3BNhXzNzONqINP .cluster-label text{fill:#333;}#mermaid-svg-1Y3BNhXzNzONqINP .cluster-label span{color:#333;}#mermaid-svg-1Y3BNhXzNzONqINP .cluster-label span p{background-color:transparent;}#mermaid-svg-1Y3BNhXzNzONqINP .label text,#mermaid-svg-1Y3BNhXzNzONqINP span{fill:#333;color:#333;}#mermaid-svg-1Y3BNhXzNzONqINP .node rect,#mermaid-svg-1Y3BNhXzNzONqINP .node circle,#mermaid-svg-1Y3BNhXzNzONqINP .node ellipse,#mermaid-svg-1Y3BNhXzNzONqINP .node polygon,#mermaid-svg-1Y3BNhXzNzONqINP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1Y3BNhXzNzONqINP .rough-node .label text,#mermaid-svg-1Y3BNhXzNzONqINP .node .label text,#mermaid-svg-1Y3BNhXzNzONqINP .image-shape .label,#mermaid-svg-1Y3BNhXzNzONqINP .icon-shape .label{text-anchor:middle;}#mermaid-svg-1Y3BNhXzNzONqINP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1Y3BNhXzNzONqINP .rough-node .label,#mermaid-svg-1Y3BNhXzNzONqINP .node .label,#mermaid-svg-1Y3BNhXzNzONqINP .image-shape .label,#mermaid-svg-1Y3BNhXzNzONqINP .icon-shape .label{text-align:center;}#mermaid-svg-1Y3BNhXzNzONqINP .node.clickable{cursor:pointer;}#mermaid-svg-1Y3BNhXzNzONqINP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1Y3BNhXzNzONqINP .arrowheadPath{fill:#333333;}#mermaid-svg-1Y3BNhXzNzONqINP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1Y3BNhXzNzONqINP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1Y3BNhXzNzONqINP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1Y3BNhXzNzONqINP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1Y3BNhXzNzONqINP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1Y3BNhXzNzONqINP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1Y3BNhXzNzONqINP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1Y3BNhXzNzONqINP .cluster text{fill:#333;}#mermaid-svg-1Y3BNhXzNzONqINP .cluster span{color:#333;}#mermaid-svg-1Y3BNhXzNzONqINP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1Y3BNhXzNzONqINP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1Y3BNhXzNzONqINP rect.text{fill:none;stroke-width:0;}#mermaid-svg-1Y3BNhXzNzONqINP .icon-shape,#mermaid-svg-1Y3BNhXzNzONqINP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1Y3BNhXzNzONqINP .icon-shape p,#mermaid-svg-1Y3BNhXzNzONqINP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1Y3BNhXzNzONqINP .icon-shape .label rect,#mermaid-svg-1Y3BNhXzNzONqINP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1Y3BNhXzNzONqINP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1Y3BNhXzNzONqINP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1Y3BNhXzNzONqINP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🟢 业务类(按需组合)
标准采购订单

V+S+C+A+ST
紧急采购订单

V+S+C+A+ST
框架采购订单

V+S+C
服务采购订单

V+S+A
🔷 能力组件(独立封装)
验证器
保存器
计算器
审批器
结算器

4.4 组合方案实现

abap 复制代码
" ================================================================
" ✅ 标准采购订单:组合全部能力
" ================================================================
CLASS zcl_standard_po DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor, process.
  PRIVATE SECTION.
    DATA: validator, saver, calculator, approver, settlement.
ENDCLASS.

CLASS zcl_standard_po IMPLEMENTATION.
  METHOD process.
    validator->validate( ).
    calculator->calculate( 10000 ).
    approver->approve( 'USER01' ).
    settlement->settle( ).
    saver->save( ).
  ENDMETHOD.
ENDCLASS.

" ================================================================
" ✅ 框架采购订单:只组合验证、保存、计算(无审批、结算)
" ================================================================
CLASS zcl_framework_po DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor, process.
  PRIVATE SECTION.
    DATA: validator, saver, calculator.
ENDCLASS.

CLASS zcl_framework_po IMPLEMENTATION.
  METHOD process.
    validator->validate( ).
    calculator->calculate( 50000 ).
    saver->save( ).
  ENDMETHOD.
ENDCLASS.

" ================================================================
" ✅ 服务采购订单:只组合验证、保存、审批(无计算、结算)
" ================================================================
CLASS zcl_service_po DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor, process.
  PRIVATE SECTION.
    DATA: validator, saver, approver.
ENDCLASS.

CLASS zcl_service_po IMPLEMENTATION.
  METHOD process.
    validator->validate( ).
    approver->approve( 'USER01' ).
    saver->save( ).
  ENDMETHOD.
ENDCLASS.

4.5 组合方案的优势

场景 继承方案 组合方案
新增订单类型 🔴 需调整继承结构 🟢 只需组合现有能力
修改验证逻辑 🔴 修改父类影响所有子类 🟢 只修改验证器类
新增"审计"能力 🔴 需修改所有子类 🟢 只需新建审计器并组合
替换实现 🔴 困难(需修改继承关系) 🟢 简单(替换组件实例)
单元测试 🔴 需测试整个继承链 🟢 可单独测试每个组件

五、继承与组合的混合使用

5.1 两者适用场景

场景 推荐方式 原因
表达"is-a"关系 🔶 继承 采购订单"是"一种订单
表达"has-a"关系 🔷 组合 采购订单"有"验证能力
模板方法模式 🔶 继承 固定流程骨架
能力组合 🔷 组合 灵活按需组合
代码复用 🔷 组合(优先) 低耦合
强制子类实现 🔶 继承 抽象方法

5.2 混合使用示例

abap 复制代码
" ================================================================
" 🔶 继承:表达层级关系("is-a")
" ================================================================
CLASS zcl_order DEFINITION ABSTRACT.
  PUBLIC SECTION.
    METHODS: process ABSTRACT.
  PROTECTED SECTION.
    DATA: order_id TYPE ebeln.
ENDCLASS.

" ================================================================
" 🔷 组合:表达能力关系("has-a")
" ================================================================
CLASS zcl_purchase_order DEFINITION INHERITING FROM zcl_order.
  PUBLIC SECTION.
    METHODS: process REDEFINITION.
  PRIVATE SECTION.
    DATA: validator TYPE REF TO zif_validatable,
          saver     TYPE REF TO zif_savable.
ENDCLASS.

CLASS zcl_purchase_order IMPLEMENTATION.
  METHOD process.
    validator->validate( ).
    saver->save( ).
  ENDMETHOD.
ENDCLASS.

六、重构:继承转组合

6.1 重构五步法

#mermaid-svg-v3C5Mnhg2kc9vnld{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-v3C5Mnhg2kc9vnld .error-icon{fill:#552222;}#mermaid-svg-v3C5Mnhg2kc9vnld .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-v3C5Mnhg2kc9vnld .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-v3C5Mnhg2kc9vnld .marker{fill:#333333;stroke:#333333;}#mermaid-svg-v3C5Mnhg2kc9vnld .marker.cross{stroke:#333333;}#mermaid-svg-v3C5Mnhg2kc9vnld svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-v3C5Mnhg2kc9vnld p{margin:0;}#mermaid-svg-v3C5Mnhg2kc9vnld .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster-label text{fill:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster-label span{color:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster-label span p{background-color:transparent;}#mermaid-svg-v3C5Mnhg2kc9vnld .label text,#mermaid-svg-v3C5Mnhg2kc9vnld span{fill:#333;color:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld .node rect,#mermaid-svg-v3C5Mnhg2kc9vnld .node circle,#mermaid-svg-v3C5Mnhg2kc9vnld .node ellipse,#mermaid-svg-v3C5Mnhg2kc9vnld .node polygon,#mermaid-svg-v3C5Mnhg2kc9vnld .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-v3C5Mnhg2kc9vnld .rough-node .label text,#mermaid-svg-v3C5Mnhg2kc9vnld .node .label text,#mermaid-svg-v3C5Mnhg2kc9vnld .image-shape .label,#mermaid-svg-v3C5Mnhg2kc9vnld .icon-shape .label{text-anchor:middle;}#mermaid-svg-v3C5Mnhg2kc9vnld .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-v3C5Mnhg2kc9vnld .rough-node .label,#mermaid-svg-v3C5Mnhg2kc9vnld .node .label,#mermaid-svg-v3C5Mnhg2kc9vnld .image-shape .label,#mermaid-svg-v3C5Mnhg2kc9vnld .icon-shape .label{text-align:center;}#mermaid-svg-v3C5Mnhg2kc9vnld .node.clickable{cursor:pointer;}#mermaid-svg-v3C5Mnhg2kc9vnld .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-v3C5Mnhg2kc9vnld .arrowheadPath{fill:#333333;}#mermaid-svg-v3C5Mnhg2kc9vnld .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-v3C5Mnhg2kc9vnld .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-v3C5Mnhg2kc9vnld .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v3C5Mnhg2kc9vnld .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-v3C5Mnhg2kc9vnld .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v3C5Mnhg2kc9vnld .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster text{fill:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld .cluster span{color:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-v3C5Mnhg2kc9vnld .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-v3C5Mnhg2kc9vnld rect.text{fill:none;stroke-width:0;}#mermaid-svg-v3C5Mnhg2kc9vnld .icon-shape,#mermaid-svg-v3C5Mnhg2kc9vnld .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v3C5Mnhg2kc9vnld .icon-shape p,#mermaid-svg-v3C5Mnhg2kc9vnld .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-v3C5Mnhg2kc9vnld .icon-shape .label rect,#mermaid-svg-v3C5Mnhg2kc9vnld .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v3C5Mnhg2kc9vnld .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-v3C5Mnhg2kc9vnld .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-v3C5Mnhg2kc9vnld :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 分析继承链
② 提取能力接口
③ 实现能力类
④ 重构子类为组合
⑤ 测试验证

6.2 重构前后对比

abap 复制代码
" ================================================================
" ❌ 重构前:继承结构(6层)
" ================================================================
CLASS zcl_standard_po DEFINITION
  INHERITING FROM zcl_purchase_order.  " 第6层
  " 继承了 validate, save, create, settle 等所有方法
  " 即使只需要其中一部分,也必须继承全部
ENDCLASS.

" ================================================================
" ✅ 重构后:组合结构(1层)
" ================================================================
CLASS zcl_standard_po DEFINITION.
  " 只组合需要的能力
  PRIVATE SECTION.
    DATA: validator  TYPE REF TO zif_validatable,
          saver      TYPE REF TO zif_savable,
          calculator TYPE REF TO zif_calculable,
          approver   TYPE REF TO zif_approvable,
          settlement TYPE REF TO zif_settlement.
ENDCLASS.

6.3 重构效果对比

指标 重构前 重构后 改进
继承层级 6层 1层 ⬇️ 83%
代码耦合 ✅ 大幅降低
新增订单类型 需修改继承结构 只需组合能力 ✅ 更灵活
单元测试 需测试6层 测试1层+组件 ⬇️ 测试成本

七、快速参考卡片

选型决策口诀

复制代码
🤔 继承还是组合?记住三问:

1. 表达"is-a"还是"has-a"?
   → "is-a"用继承,"has-a"用组合

2. 层级是否超过3层?
   → 超过3层,考虑用组合重构

3. 需要灵活组合多种能力吗?
   → 需要 → 用组合 + 接口

最佳实践速查

原则 说明
层级限制 继承层级不超过3层
职责单一 每个类只负责一个核心职责
接口优先 通过接口引用组合对象
组合优先 优先使用组合实现能力复用
依赖注入 通过构造函数注入依赖

八、总结

#mermaid-svg-wGC1Lj6F8Ks8K112{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wGC1Lj6F8Ks8K112 .error-icon{fill:#552222;}#mermaid-svg-wGC1Lj6F8Ks8K112 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wGC1Lj6F8Ks8K112 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .marker.cross{stroke:#333333;}#mermaid-svg-wGC1Lj6F8Ks8K112 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wGC1Lj6F8Ks8K112 p{margin:0;}#mermaid-svg-wGC1Lj6F8Ks8K112 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster-label text{fill:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster-label span{color:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster-label span p{background-color:transparent;}#mermaid-svg-wGC1Lj6F8Ks8K112 .label text,#mermaid-svg-wGC1Lj6F8Ks8K112 span{fill:#333;color:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .node rect,#mermaid-svg-wGC1Lj6F8Ks8K112 .node circle,#mermaid-svg-wGC1Lj6F8Ks8K112 .node ellipse,#mermaid-svg-wGC1Lj6F8Ks8K112 .node polygon,#mermaid-svg-wGC1Lj6F8Ks8K112 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .rough-node .label text,#mermaid-svg-wGC1Lj6F8Ks8K112 .node .label text,#mermaid-svg-wGC1Lj6F8Ks8K112 .image-shape .label,#mermaid-svg-wGC1Lj6F8Ks8K112 .icon-shape .label{text-anchor:middle;}#mermaid-svg-wGC1Lj6F8Ks8K112 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .rough-node .label,#mermaid-svg-wGC1Lj6F8Ks8K112 .node .label,#mermaid-svg-wGC1Lj6F8Ks8K112 .image-shape .label,#mermaid-svg-wGC1Lj6F8Ks8K112 .icon-shape .label{text-align:center;}#mermaid-svg-wGC1Lj6F8Ks8K112 .node.clickable{cursor:pointer;}#mermaid-svg-wGC1Lj6F8Ks8K112 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .arrowheadPath{fill:#333333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wGC1Lj6F8Ks8K112 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wGC1Lj6F8Ks8K112 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wGC1Lj6F8Ks8K112 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster text{fill:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 .cluster span{color:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wGC1Lj6F8Ks8K112 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wGC1Lj6F8Ks8K112 rect.text{fill:none;stroke-width:0;}#mermaid-svg-wGC1Lj6F8Ks8K112 .icon-shape,#mermaid-svg-wGC1Lj6F8Ks8K112 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wGC1Lj6F8Ks8K112 .icon-shape p,#mermaid-svg-wGC1Lj6F8Ks8K112 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wGC1Lj6F8Ks8K112 .icon-shape .label rect,#mermaid-svg-wGC1Lj6F8Ks8K112 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wGC1Lj6F8Ks8K112 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wGC1Lj6F8Ks8K112 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wGC1Lj6F8Ks8K112 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 代码复用方案
🔶 继承
🔷 组合
'is-a'关系
层级结构
模板方法
'has-a'关系
能力组合
灵活扩展

核心要点 说明
继承层级控制 不超过3层,超过考虑组合
组合优先 优先使用组合实现能力复用
接口结合 通过接口引用组合对象,便于替换
混合使用 继承表达层级,组合表达能力
单一职责 每个类/组件只负责一个核心职责

下一篇预告:《避坑指南:继承、多态与接口开发的10个典型错误与排查方案》

作者 :爱喝水的鱼丶

版本记录 :2026年7月

验证基准:SAP NetWeaver 7.51

💬 你在实际项目中遇到过继承层级过深的问题吗?是如何解决的?欢迎在评论区分享你的经验!