Intro to Design Patterns
Welcome to Design Patterns


SimUDuck应用程序

一个模拟鸭子游戏:SimUDuck。游戏中会出现各种鸭子,一边游泳,一边呱呱叫。此系统设计了一个鸭子超类 (Superclass),并让各种鸭子继承此超类。

#mermaid-svg-JBf6pPMTHXoRic5E .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-JBf6pPMTHXoRic5E .label text{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .node rect,#mermaid-svg-JBf6pPMTHXoRic5E .node circle,#mermaid-svg-JBf6pPMTHXoRic5E .node ellipse,#mermaid-svg-JBf6pPMTHXoRic5E .node polygon,#mermaid-svg-JBf6pPMTHXoRic5E .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-JBf6pPMTHXoRic5E .node .label{text-align:center;fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .node.clickable{cursor:pointer}#mermaid-svg-JBf6pPMTHXoRic5E .arrowheadPath{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-JBf6pPMTHXoRic5E .flowchart-link{stroke:#333;fill:none}#mermaid-svg-JBf6pPMTHXoRic5E .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-JBf6pPMTHXoRic5E .edgeLabel rect{opacity:0.9}#mermaid-svg-JBf6pPMTHXoRic5E .edgeLabel span{color:#333}#mermaid-svg-JBf6pPMTHXoRic5E .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-JBf6pPMTHXoRic5E .cluster text{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-JBf6pPMTHXoRic5E .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-JBf6pPMTHXoRic5E text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-JBf6pPMTHXoRic5E .actor-line{stroke:grey}#mermaid-svg-JBf6pPMTHXoRic5E .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-JBf6pPMTHXoRic5E .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-JBf6pPMTHXoRic5E #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-JBf6pPMTHXoRic5E .sequenceNumber{fill:#fff}#mermaid-svg-JBf6pPMTHXoRic5E #sequencenumber{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E #crosshead path{fill:#333;stroke:#333}#mermaid-svg-JBf6pPMTHXoRic5E .messageText{fill:#333;stroke:#333}#mermaid-svg-JBf6pPMTHXoRic5E .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-JBf6pPMTHXoRic5E .labelText,#mermaid-svg-JBf6pPMTHXoRic5E .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-JBf6pPMTHXoRic5E .loopText,#mermaid-svg-JBf6pPMTHXoRic5E .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-JBf6pPMTHXoRic5E .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-JBf6pPMTHXoRic5E .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-JBf6pPMTHXoRic5E .noteText,#mermaid-svg-JBf6pPMTHXoRic5E .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-JBf6pPMTHXoRic5E .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-JBf6pPMTHXoRic5E .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-JBf6pPMTHXoRic5E .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-JBf6pPMTHXoRic5E .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .section{stroke:none;opacity:0.2}#mermaid-svg-JBf6pPMTHXoRic5E .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-JBf6pPMTHXoRic5E .section2{fill:#fff400}#mermaid-svg-JBf6pPMTHXoRic5E .section1,#mermaid-svg-JBf6pPMTHXoRic5E .section3{fill:#fff;opacity:0.2}#mermaid-svg-JBf6pPMTHXoRic5E .sectionTitle0{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .sectionTitle1{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .sectionTitle2{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .sectionTitle3{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-JBf6pPMTHXoRic5E .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .grid path{stroke-width:0}#mermaid-svg-JBf6pPMTHXoRic5E .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-JBf6pPMTHXoRic5E .task{stroke-width:2}#mermaid-svg-JBf6pPMTHXoRic5E .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .taskText:not([font-size]){font-size:11px}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-JBf6pPMTHXoRic5E .task.clickable{cursor:pointer}#mermaid-svg-JBf6pPMTHXoRic5E .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JBf6pPMTHXoRic5E .taskText0,#mermaid-svg-JBf6pPMTHXoRic5E .taskText1,#mermaid-svg-JBf6pPMTHXoRic5E .taskText2,#mermaid-svg-JBf6pPMTHXoRic5E .taskText3{fill:#fff}#mermaid-svg-JBf6pPMTHXoRic5E .task0,#mermaid-svg-JBf6pPMTHXoRic5E .task1,#mermaid-svg-JBf6pPMTHXoRic5E .task2,#mermaid-svg-JBf6pPMTHXoRic5E .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutside0,#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutside2{fill:#000}#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutside1,#mermaid-svg-JBf6pPMTHXoRic5E .taskTextOutside3{fill:#000}#mermaid-svg-JBf6pPMTHXoRic5E .active0,#mermaid-svg-JBf6pPMTHXoRic5E .active1,#mermaid-svg-JBf6pPMTHXoRic5E .active2,#mermaid-svg-JBf6pPMTHXoRic5E .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-JBf6pPMTHXoRic5E .activeText0,#mermaid-svg-JBf6pPMTHXoRic5E .activeText1,#mermaid-svg-JBf6pPMTHXoRic5E .activeText2,#mermaid-svg-JBf6pPMTHXoRic5E .activeText3{fill:#000 !important}#mermaid-svg-JBf6pPMTHXoRic5E .done0,#mermaid-svg-JBf6pPMTHXoRic5E .done1,#mermaid-svg-JBf6pPMTHXoRic5E .done2,#mermaid-svg-JBf6pPMTHXoRic5E .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-JBf6pPMTHXoRic5E .doneText0,#mermaid-svg-JBf6pPMTHXoRic5E .doneText1,#mermaid-svg-JBf6pPMTHXoRic5E .doneText2,#mermaid-svg-JBf6pPMTHXoRic5E .doneText3{fill:#000 !important}#mermaid-svg-JBf6pPMTHXoRic5E .crit0,#mermaid-svg-JBf6pPMTHXoRic5E .crit1,#mermaid-svg-JBf6pPMTHXoRic5E .crit2,#mermaid-svg-JBf6pPMTHXoRic5E .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-JBf6pPMTHXoRic5E .activeCrit0,#mermaid-svg-JBf6pPMTHXoRic5E .activeCrit1,#mermaid-svg-JBf6pPMTHXoRic5E .activeCrit2,#mermaid-svg-JBf6pPMTHXoRic5E .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-JBf6pPMTHXoRic5E .doneCrit0,#mermaid-svg-JBf6pPMTHXoRic5E .doneCrit1,#mermaid-svg-JBf6pPMTHXoRic5E .doneCrit2,#mermaid-svg-JBf6pPMTHXoRic5E .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-JBf6pPMTHXoRic5E .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-JBf6pPMTHXoRic5E .milestoneText{font-style:italic}#mermaid-svg-JBf6pPMTHXoRic5E .doneCritText0,#mermaid-svg-JBf6pPMTHXoRic5E .doneCritText1,#mermaid-svg-JBf6pPMTHXoRic5E .doneCritText2,#mermaid-svg-JBf6pPMTHXoRic5E .doneCritText3{fill:#000 !important}#mermaid-svg-JBf6pPMTHXoRic5E .activeCritText0,#mermaid-svg-JBf6pPMTHXoRic5E .activeCritText1,#mermaid-svg-JBf6pPMTHXoRic5E .activeCritText2,#mermaid-svg-JBf6pPMTHXoRic5E .activeCritText3{fill:#000 !important}#mermaid-svg-JBf6pPMTHXoRic5E .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-JBf6pPMTHXoRic5E g.classGroup text .title{font-weight:bolder}#mermaid-svg-JBf6pPMTHXoRic5E g.clickable{cursor:pointer}#mermaid-svg-JBf6pPMTHXoRic5E g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-JBf6pPMTHXoRic5E g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-JBf6pPMTHXoRic5E .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-JBf6pPMTHXoRic5E .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-JBf6pPMTHXoRic5E .dashed-line{stroke-dasharray:3}#mermaid-svg-JBf6pPMTHXoRic5E #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E .commit-id,#mermaid-svg-JBf6pPMTHXoRic5E .commit-msg,#mermaid-svg-JBf6pPMTHXoRic5E .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-JBf6pPMTHXoRic5E g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-JBf6pPMTHXoRic5E g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-JBf6pPMTHXoRic5E g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-JBf6pPMTHXoRic5E .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-JBf6pPMTHXoRic5E .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-JBf6pPMTHXoRic5E .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-JBf6pPMTHXoRic5E .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-JBf6pPMTHXoRic5E .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-JBf6pPMTHXoRic5E .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-JBf6pPMTHXoRic5E .edgeLabel text{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JBf6pPMTHXoRic5E .node circle.state-start{fill:black;stroke:black}#mermaid-svg-JBf6pPMTHXoRic5E .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-JBf6pPMTHXoRic5E #statediagram-barbEnd{fill:#9370db}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-state .divider{stroke:#9370db}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-JBf6pPMTHXoRic5E .note-edge{stroke-dasharray:5}#mermaid-svg-JBf6pPMTHXoRic5E .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-JBf6pPMTHXoRic5E .error-icon{fill:#522}#mermaid-svg-JBf6pPMTHXoRic5E .error-text{fill:#522;stroke:#522}#mermaid-svg-JBf6pPMTHXoRic5E .edge-thickness-normal{stroke-width:2px}#mermaid-svg-JBf6pPMTHXoRic5E .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-JBf6pPMTHXoRic5E .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-JBf6pPMTHXoRic5E .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-JBf6pPMTHXoRic5E .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-JBf6pPMTHXoRic5E .marker{fill:#333}#mermaid-svg-JBf6pPMTHXoRic5E .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-JBf6pPMTHXoRic5E {color: rgba(0, 0, 0, 0.75);font: ;}MallardDuckdisplay()Duckquack()swim()display()RedheadDuckdisplay()OtherDuck

每个鸭子的子类型负责实现自己的 display() 行为,在屏幕上显示其外观。MallardDuck 外观是绿头,RedheadDuck 外观是红头。

软件开发的一个不变真理:改变

问题:改变程序,让鸭子能飞。

如果在 Duck 类中添加成员 fly(),会导致所有子类都具备 fly(),连那些不该具备 fly() 的类都不能免除。
例如,橡皮鸭不会飞,叫声是吱吱叫。

#mermaid-svg-rtj2FAz6M1ltkVJb .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .label text{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .node rect,#mermaid-svg-rtj2FAz6M1ltkVJb .node circle,#mermaid-svg-rtj2FAz6M1ltkVJb .node ellipse,#mermaid-svg-rtj2FAz6M1ltkVJb .node polygon,#mermaid-svg-rtj2FAz6M1ltkVJb .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-rtj2FAz6M1ltkVJb .node .label{text-align:center;fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .node.clickable{cursor:pointer}#mermaid-svg-rtj2FAz6M1ltkVJb .arrowheadPath{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-rtj2FAz6M1ltkVJb .flowchart-link{stroke:#333;fill:none}#mermaid-svg-rtj2FAz6M1ltkVJb .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-rtj2FAz6M1ltkVJb .edgeLabel rect{opacity:0.9}#mermaid-svg-rtj2FAz6M1ltkVJb .edgeLabel span{color:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-rtj2FAz6M1ltkVJb .cluster text{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-rtj2FAz6M1ltkVJb .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-rtj2FAz6M1ltkVJb text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-rtj2FAz6M1ltkVJb .actor-line{stroke:grey}#mermaid-svg-rtj2FAz6M1ltkVJb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-rtj2FAz6M1ltkVJb #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .sequenceNumber{fill:#fff}#mermaid-svg-rtj2FAz6M1ltkVJb #sequencenumber{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb #crosshead path{fill:#333;stroke:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .messageText{fill:#333;stroke:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-rtj2FAz6M1ltkVJb .labelText,#mermaid-svg-rtj2FAz6M1ltkVJb .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-rtj2FAz6M1ltkVJb .loopText,#mermaid-svg-rtj2FAz6M1ltkVJb .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-rtj2FAz6M1ltkVJb .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-rtj2FAz6M1ltkVJb .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-rtj2FAz6M1ltkVJb .noteText,#mermaid-svg-rtj2FAz6M1ltkVJb .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-rtj2FAz6M1ltkVJb .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-rtj2FAz6M1ltkVJb .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-rtj2FAz6M1ltkVJb .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-rtj2FAz6M1ltkVJb .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .section{stroke:none;opacity:0.2}#mermaid-svg-rtj2FAz6M1ltkVJb .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-rtj2FAz6M1ltkVJb .section2{fill:#fff400}#mermaid-svg-rtj2FAz6M1ltkVJb .section1,#mermaid-svg-rtj2FAz6M1ltkVJb .section3{fill:#fff;opacity:0.2}#mermaid-svg-rtj2FAz6M1ltkVJb .sectionTitle0{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .sectionTitle1{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .sectionTitle2{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .sectionTitle3{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-rtj2FAz6M1ltkVJb .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .grid path{stroke-width:0}#mermaid-svg-rtj2FAz6M1ltkVJb .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-rtj2FAz6M1ltkVJb .task{stroke-width:2}#mermaid-svg-rtj2FAz6M1ltkVJb .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .taskText:not([font-size]){font-size:11px}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-rtj2FAz6M1ltkVJb .task.clickable{cursor:pointer}#mermaid-svg-rtj2FAz6M1ltkVJb .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-rtj2FAz6M1ltkVJb .taskText0,#mermaid-svg-rtj2FAz6M1ltkVJb .taskText1,#mermaid-svg-rtj2FAz6M1ltkVJb .taskText2,#mermaid-svg-rtj2FAz6M1ltkVJb .taskText3{fill:#fff}#mermaid-svg-rtj2FAz6M1ltkVJb .task0,#mermaid-svg-rtj2FAz6M1ltkVJb .task1,#mermaid-svg-rtj2FAz6M1ltkVJb .task2,#mermaid-svg-rtj2FAz6M1ltkVJb .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutside0,#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutside2{fill:#000}#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutside1,#mermaid-svg-rtj2FAz6M1ltkVJb .taskTextOutside3{fill:#000}#mermaid-svg-rtj2FAz6M1ltkVJb .active0,#mermaid-svg-rtj2FAz6M1ltkVJb .active1,#mermaid-svg-rtj2FAz6M1ltkVJb .active2,#mermaid-svg-rtj2FAz6M1ltkVJb .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-rtj2FAz6M1ltkVJb .activeText0,#mermaid-svg-rtj2FAz6M1ltkVJb .activeText1,#mermaid-svg-rtj2FAz6M1ltkVJb .activeText2,#mermaid-svg-rtj2FAz6M1ltkVJb .activeText3{fill:#000 !important}#mermaid-svg-rtj2FAz6M1ltkVJb .done0,#mermaid-svg-rtj2FAz6M1ltkVJb .done1,#mermaid-svg-rtj2FAz6M1ltkVJb .done2,#mermaid-svg-rtj2FAz6M1ltkVJb .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-rtj2FAz6M1ltkVJb .doneText0,#mermaid-svg-rtj2FAz6M1ltkVJb .doneText1,#mermaid-svg-rtj2FAz6M1ltkVJb .doneText2,#mermaid-svg-rtj2FAz6M1ltkVJb .doneText3{fill:#000 !important}#mermaid-svg-rtj2FAz6M1ltkVJb .crit0,#mermaid-svg-rtj2FAz6M1ltkVJb .crit1,#mermaid-svg-rtj2FAz6M1ltkVJb .crit2,#mermaid-svg-rtj2FAz6M1ltkVJb .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-rtj2FAz6M1ltkVJb .activeCrit0,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCrit1,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCrit2,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-rtj2FAz6M1ltkVJb .doneCrit0,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCrit1,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCrit2,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-rtj2FAz6M1ltkVJb .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-rtj2FAz6M1ltkVJb .milestoneText{font-style:italic}#mermaid-svg-rtj2FAz6M1ltkVJb .doneCritText0,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCritText1,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCritText2,#mermaid-svg-rtj2FAz6M1ltkVJb .doneCritText3{fill:#000 !important}#mermaid-svg-rtj2FAz6M1ltkVJb .activeCritText0,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCritText1,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCritText2,#mermaid-svg-rtj2FAz6M1ltkVJb .activeCritText3{fill:#000 !important}#mermaid-svg-rtj2FAz6M1ltkVJb .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-rtj2FAz6M1ltkVJb g.classGroup text .title{font-weight:bolder}#mermaid-svg-rtj2FAz6M1ltkVJb g.clickable{cursor:pointer}#mermaid-svg-rtj2FAz6M1ltkVJb g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-rtj2FAz6M1ltkVJb g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-rtj2FAz6M1ltkVJb .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-rtj2FAz6M1ltkVJb .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-rtj2FAz6M1ltkVJb .dashed-line{stroke-dasharray:3}#mermaid-svg-rtj2FAz6M1ltkVJb #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb .commit-id,#mermaid-svg-rtj2FAz6M1ltkVJb .commit-msg,#mermaid-svg-rtj2FAz6M1ltkVJb .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-rtj2FAz6M1ltkVJb g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-rtj2FAz6M1ltkVJb g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-rtj2FAz6M1ltkVJb g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-rtj2FAz6M1ltkVJb .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-rtj2FAz6M1ltkVJb .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-rtj2FAz6M1ltkVJb .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-rtj2FAz6M1ltkVJb .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-rtj2FAz6M1ltkVJb .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-rtj2FAz6M1ltkVJb .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-rtj2FAz6M1ltkVJb .edgeLabel text{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-rtj2FAz6M1ltkVJb .node circle.state-start{fill:black;stroke:black}#mermaid-svg-rtj2FAz6M1ltkVJb .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-rtj2FAz6M1ltkVJb #statediagram-barbEnd{fill:#9370db}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-state .divider{stroke:#9370db}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-rtj2FAz6M1ltkVJb .note-edge{stroke-dasharray:5}#mermaid-svg-rtj2FAz6M1ltkVJb .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-rtj2FAz6M1ltkVJb .error-icon{fill:#522}#mermaid-svg-rtj2FAz6M1ltkVJb .error-text{fill:#522;stroke:#522}#mermaid-svg-rtj2FAz6M1ltkVJb .edge-thickness-normal{stroke-width:2px}#mermaid-svg-rtj2FAz6M1ltkVJb .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-rtj2FAz6M1ltkVJb .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-rtj2FAz6M1ltkVJb .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-rtj2FAz6M1ltkVJb .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-rtj2FAz6M1ltkVJb .marker{fill:#333}#mermaid-svg-rtj2FAz6M1ltkVJb .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-rtj2FAz6M1ltkVJb {color: rgba(0, 0, 0, 0.75);font: ;}RubberDuckquack()display()fly()

可以覆盖橡皮鸭中的 fly() 方法,变成什么事都不做。

但是规范会不断变化,比如增加诱饵鸭,它不会飞也不会叫。这样开发人员总是需要检查,且可能重写程序中每个新的 Duck 子类的 fly() 和 quack()。

利用继承来提供 Duck 行为,会导致以下缺点:

  • 代码在多个子类中重复
  • 运行时的行为不容易改变
  • 很难知道所有鸭子的全部行为
  • 改变会牵一发动全身,造成其他鸭子不想要的改变

换一种方式,使用接口:将 fly() 从 Duck 超类中取出,并使用 fly() 方法创建 Flyable() 接口。这样,只有应该会飞的鸭子才能实现该接口并具有 fly() 方法,同理,创建 Quackable 接口。

#mermaid-svg-m1bdJi3IJw0Z34EF .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .label text{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .node rect,#mermaid-svg-m1bdJi3IJw0Z34EF .node circle,#mermaid-svg-m1bdJi3IJw0Z34EF .node ellipse,#mermaid-svg-m1bdJi3IJw0Z34EF .node polygon,#mermaid-svg-m1bdJi3IJw0Z34EF .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-m1bdJi3IJw0Z34EF .node .label{text-align:center;fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .node.clickable{cursor:pointer}#mermaid-svg-m1bdJi3IJw0Z34EF .arrowheadPath{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-m1bdJi3IJw0Z34EF .flowchart-link{stroke:#333;fill:none}#mermaid-svg-m1bdJi3IJw0Z34EF .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-m1bdJi3IJw0Z34EF .edgeLabel rect{opacity:0.9}#mermaid-svg-m1bdJi3IJw0Z34EF .edgeLabel span{color:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-m1bdJi3IJw0Z34EF .cluster text{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-m1bdJi3IJw0Z34EF .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-m1bdJi3IJw0Z34EF text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-m1bdJi3IJw0Z34EF .actor-line{stroke:grey}#mermaid-svg-m1bdJi3IJw0Z34EF .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-m1bdJi3IJw0Z34EF #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .sequenceNumber{fill:#fff}#mermaid-svg-m1bdJi3IJw0Z34EF #sequencenumber{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF #crosshead path{fill:#333;stroke:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .messageText{fill:#333;stroke:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-m1bdJi3IJw0Z34EF .labelText,#mermaid-svg-m1bdJi3IJw0Z34EF .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-m1bdJi3IJw0Z34EF .loopText,#mermaid-svg-m1bdJi3IJw0Z34EF .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-m1bdJi3IJw0Z34EF .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-m1bdJi3IJw0Z34EF .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-m1bdJi3IJw0Z34EF .noteText,#mermaid-svg-m1bdJi3IJw0Z34EF .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-m1bdJi3IJw0Z34EF .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-m1bdJi3IJw0Z34EF .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-m1bdJi3IJw0Z34EF .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-m1bdJi3IJw0Z34EF .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .section{stroke:none;opacity:0.2}#mermaid-svg-m1bdJi3IJw0Z34EF .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-m1bdJi3IJw0Z34EF .section2{fill:#fff400}#mermaid-svg-m1bdJi3IJw0Z34EF .section1,#mermaid-svg-m1bdJi3IJw0Z34EF .section3{fill:#fff;opacity:0.2}#mermaid-svg-m1bdJi3IJw0Z34EF .sectionTitle0{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .sectionTitle1{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .sectionTitle2{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .sectionTitle3{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-m1bdJi3IJw0Z34EF .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .grid path{stroke-width:0}#mermaid-svg-m1bdJi3IJw0Z34EF .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-m1bdJi3IJw0Z34EF .task{stroke-width:2}#mermaid-svg-m1bdJi3IJw0Z34EF .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .taskText:not([font-size]){font-size:11px}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-m1bdJi3IJw0Z34EF .task.clickable{cursor:pointer}#mermaid-svg-m1bdJi3IJw0Z34EF .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-m1bdJi3IJw0Z34EF .taskText0,#mermaid-svg-m1bdJi3IJw0Z34EF .taskText1,#mermaid-svg-m1bdJi3IJw0Z34EF .taskText2,#mermaid-svg-m1bdJi3IJw0Z34EF .taskText3{fill:#fff}#mermaid-svg-m1bdJi3IJw0Z34EF .task0,#mermaid-svg-m1bdJi3IJw0Z34EF .task1,#mermaid-svg-m1bdJi3IJw0Z34EF .task2,#mermaid-svg-m1bdJi3IJw0Z34EF .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutside0,#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutside2{fill:#000}#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutside1,#mermaid-svg-m1bdJi3IJw0Z34EF .taskTextOutside3{fill:#000}#mermaid-svg-m1bdJi3IJw0Z34EF .active0,#mermaid-svg-m1bdJi3IJw0Z34EF .active1,#mermaid-svg-m1bdJi3IJw0Z34EF .active2,#mermaid-svg-m1bdJi3IJw0Z34EF .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-m1bdJi3IJw0Z34EF .activeText0,#mermaid-svg-m1bdJi3IJw0Z34EF .activeText1,#mermaid-svg-m1bdJi3IJw0Z34EF .activeText2,#mermaid-svg-m1bdJi3IJw0Z34EF .activeText3{fill:#000 !important}#mermaid-svg-m1bdJi3IJw0Z34EF .done0,#mermaid-svg-m1bdJi3IJw0Z34EF .done1,#mermaid-svg-m1bdJi3IJw0Z34EF .done2,#mermaid-svg-m1bdJi3IJw0Z34EF .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-m1bdJi3IJw0Z34EF .doneText0,#mermaid-svg-m1bdJi3IJw0Z34EF .doneText1,#mermaid-svg-m1bdJi3IJw0Z34EF .doneText2,#mermaid-svg-m1bdJi3IJw0Z34EF .doneText3{fill:#000 !important}#mermaid-svg-m1bdJi3IJw0Z34EF .crit0,#mermaid-svg-m1bdJi3IJw0Z34EF .crit1,#mermaid-svg-m1bdJi3IJw0Z34EF .crit2,#mermaid-svg-m1bdJi3IJw0Z34EF .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-m1bdJi3IJw0Z34EF .activeCrit0,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCrit1,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCrit2,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-m1bdJi3IJw0Z34EF .doneCrit0,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCrit1,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCrit2,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-m1bdJi3IJw0Z34EF .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-m1bdJi3IJw0Z34EF .milestoneText{font-style:italic}#mermaid-svg-m1bdJi3IJw0Z34EF .doneCritText0,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCritText1,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCritText2,#mermaid-svg-m1bdJi3IJw0Z34EF .doneCritText3{fill:#000 !important}#mermaid-svg-m1bdJi3IJw0Z34EF .activeCritText0,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCritText1,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCritText2,#mermaid-svg-m1bdJi3IJw0Z34EF .activeCritText3{fill:#000 !important}#mermaid-svg-m1bdJi3IJw0Z34EF .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-m1bdJi3IJw0Z34EF g.classGroup text .title{font-weight:bolder}#mermaid-svg-m1bdJi3IJw0Z34EF g.clickable{cursor:pointer}#mermaid-svg-m1bdJi3IJw0Z34EF g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-m1bdJi3IJw0Z34EF g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-m1bdJi3IJw0Z34EF .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-m1bdJi3IJw0Z34EF .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-m1bdJi3IJw0Z34EF .dashed-line{stroke-dasharray:3}#mermaid-svg-m1bdJi3IJw0Z34EF #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF .commit-id,#mermaid-svg-m1bdJi3IJw0Z34EF .commit-msg,#mermaid-svg-m1bdJi3IJw0Z34EF .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-m1bdJi3IJw0Z34EF g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-m1bdJi3IJw0Z34EF g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-m1bdJi3IJw0Z34EF g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-m1bdJi3IJw0Z34EF .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-m1bdJi3IJw0Z34EF .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-m1bdJi3IJw0Z34EF .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-m1bdJi3IJw0Z34EF .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-m1bdJi3IJw0Z34EF .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-m1bdJi3IJw0Z34EF .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-m1bdJi3IJw0Z34EF .edgeLabel text{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-m1bdJi3IJw0Z34EF .node circle.state-start{fill:black;stroke:black}#mermaid-svg-m1bdJi3IJw0Z34EF .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-m1bdJi3IJw0Z34EF #statediagram-barbEnd{fill:#9370db}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-state .divider{stroke:#9370db}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-m1bdJi3IJw0Z34EF .note-edge{stroke-dasharray:5}#mermaid-svg-m1bdJi3IJw0Z34EF .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-m1bdJi3IJw0Z34EF .error-icon{fill:#522}#mermaid-svg-m1bdJi3IJw0Z34EF .error-text{fill:#522;stroke:#522}#mermaid-svg-m1bdJi3IJw0Z34EF .edge-thickness-normal{stroke-width:2px}#mermaid-svg-m1bdJi3IJw0Z34EF .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-m1bdJi3IJw0Z34EF .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-m1bdJi3IJw0Z34EF .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-m1bdJi3IJw0Z34EF .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-m1bdJi3IJw0Z34EF .marker{fill:#333}#mermaid-svg-m1bdJi3IJw0Z34EF .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-m1bdJi3IJw0Z34EF {color: rgba(0, 0, 0, 0.75);font: ;}MallardDuckdisplay()fly()quack()Duckswim()display()RedheadDuckdisplay()fly()quack()RubberDuckdisplay()quack()DecoyDuckdisplay()Flyablefly()Quackablequack()

虽然接口可以解决部分问题——不会再有会飞的橡皮鸭,但是却造成代码无法复用。甚至,鸭子的飞行姿势可能会有多种变化,而且会出现叫声不同的情况。

设计原则一

现在已经知道,继承与接口并不能很好地解决问题。有一个设计原则,可以适用这种情况。

设计原则1:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的混在一起。

下面是这个原则的另一种思考方式:把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要改变的其他部分。

结果如何?代码变化引起的不经意后果变少,系统变得更有灵活性。

分开变化和不会变化的部分

将 quack() 和 fly() 两个行为从 Duck 类中分开:把它们从 Duck 类中取出来,建立一组新类来代表每个行为。

设计原则二

如何设计一组实现 fly 和 quack 行为的类呢?

让鸭子的行为变得灵活。而且要将行为赋值给 Duck 实例。
例如,实例化一个新的 MallardDuck 实例,并使用特定类型的飞行行为对其初始化。这时,可以动态地改变鸭子的行为。即,应该在 Duck 类中包含设定行为的方法,以便在运行时改变 MallardDuck 的飞行行为。

设计原则2:针对接口编程,而不是针对实现编程。

利用接口表示每个行为,比如 FlyBehavior 和 QuackBehavior,一个行为的每个实现将实现其中一个接口。

这样,Duck 类不需要知道它们自己行为的实现细节。

“针对接口编程”真正的意思是“针对超类型编程”

“针对接口编程”的关键是利用多态,这可通过对超类型编程来实现,以使实际的运行时对象不会被锁定在代码中。

可以将“针对超类型编程”改写为“变量的声明类型应该是超类型,通常是抽象类或接口,以便赋值给这些变量的对象可以是超类型的任何具体实现,这意味着声明它们的类不必知道实际的对象类型!”

例如,假设有一个抽象类 Animal,它有两个具体的实现类 Dog 和 Cat。

#mermaid-svg-tAqaUW9c2m5tTblh .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-tAqaUW9c2m5tTblh .label text{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .node rect,#mermaid-svg-tAqaUW9c2m5tTblh .node circle,#mermaid-svg-tAqaUW9c2m5tTblh .node ellipse,#mermaid-svg-tAqaUW9c2m5tTblh .node polygon,#mermaid-svg-tAqaUW9c2m5tTblh .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-tAqaUW9c2m5tTblh .node .label{text-align:center;fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .node.clickable{cursor:pointer}#mermaid-svg-tAqaUW9c2m5tTblh .arrowheadPath{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-tAqaUW9c2m5tTblh .flowchart-link{stroke:#333;fill:none}#mermaid-svg-tAqaUW9c2m5tTblh .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-tAqaUW9c2m5tTblh .edgeLabel rect{opacity:0.9}#mermaid-svg-tAqaUW9c2m5tTblh .edgeLabel span{color:#333}#mermaid-svg-tAqaUW9c2m5tTblh .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-tAqaUW9c2m5tTblh .cluster text{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-tAqaUW9c2m5tTblh .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-tAqaUW9c2m5tTblh text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-tAqaUW9c2m5tTblh .actor-line{stroke:grey}#mermaid-svg-tAqaUW9c2m5tTblh .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-tAqaUW9c2m5tTblh .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-tAqaUW9c2m5tTblh #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-tAqaUW9c2m5tTblh .sequenceNumber{fill:#fff}#mermaid-svg-tAqaUW9c2m5tTblh #sequencenumber{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh #crosshead path{fill:#333;stroke:#333}#mermaid-svg-tAqaUW9c2m5tTblh .messageText{fill:#333;stroke:#333}#mermaid-svg-tAqaUW9c2m5tTblh .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-tAqaUW9c2m5tTblh .labelText,#mermaid-svg-tAqaUW9c2m5tTblh .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-tAqaUW9c2m5tTblh .loopText,#mermaid-svg-tAqaUW9c2m5tTblh .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-tAqaUW9c2m5tTblh .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-tAqaUW9c2m5tTblh .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-tAqaUW9c2m5tTblh .noteText,#mermaid-svg-tAqaUW9c2m5tTblh .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-tAqaUW9c2m5tTblh .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-tAqaUW9c2m5tTblh .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-tAqaUW9c2m5tTblh .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-tAqaUW9c2m5tTblh .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .section{stroke:none;opacity:0.2}#mermaid-svg-tAqaUW9c2m5tTblh .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-tAqaUW9c2m5tTblh .section2{fill:#fff400}#mermaid-svg-tAqaUW9c2m5tTblh .section1,#mermaid-svg-tAqaUW9c2m5tTblh .section3{fill:#fff;opacity:0.2}#mermaid-svg-tAqaUW9c2m5tTblh .sectionTitle0{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .sectionTitle1{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .sectionTitle2{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .sectionTitle3{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-tAqaUW9c2m5tTblh .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .grid path{stroke-width:0}#mermaid-svg-tAqaUW9c2m5tTblh .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-tAqaUW9c2m5tTblh .task{stroke-width:2}#mermaid-svg-tAqaUW9c2m5tTblh .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .taskText:not([font-size]){font-size:11px}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-tAqaUW9c2m5tTblh .task.clickable{cursor:pointer}#mermaid-svg-tAqaUW9c2m5tTblh .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-tAqaUW9c2m5tTblh .taskText0,#mermaid-svg-tAqaUW9c2m5tTblh .taskText1,#mermaid-svg-tAqaUW9c2m5tTblh .taskText2,#mermaid-svg-tAqaUW9c2m5tTblh .taskText3{fill:#fff}#mermaid-svg-tAqaUW9c2m5tTblh .task0,#mermaid-svg-tAqaUW9c2m5tTblh .task1,#mermaid-svg-tAqaUW9c2m5tTblh .task2,#mermaid-svg-tAqaUW9c2m5tTblh .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutside0,#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutside2{fill:#000}#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutside1,#mermaid-svg-tAqaUW9c2m5tTblh .taskTextOutside3{fill:#000}#mermaid-svg-tAqaUW9c2m5tTblh .active0,#mermaid-svg-tAqaUW9c2m5tTblh .active1,#mermaid-svg-tAqaUW9c2m5tTblh .active2,#mermaid-svg-tAqaUW9c2m5tTblh .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-tAqaUW9c2m5tTblh .activeText0,#mermaid-svg-tAqaUW9c2m5tTblh .activeText1,#mermaid-svg-tAqaUW9c2m5tTblh .activeText2,#mermaid-svg-tAqaUW9c2m5tTblh .activeText3{fill:#000 !important}#mermaid-svg-tAqaUW9c2m5tTblh .done0,#mermaid-svg-tAqaUW9c2m5tTblh .done1,#mermaid-svg-tAqaUW9c2m5tTblh .done2,#mermaid-svg-tAqaUW9c2m5tTblh .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-tAqaUW9c2m5tTblh .doneText0,#mermaid-svg-tAqaUW9c2m5tTblh .doneText1,#mermaid-svg-tAqaUW9c2m5tTblh .doneText2,#mermaid-svg-tAqaUW9c2m5tTblh .doneText3{fill:#000 !important}#mermaid-svg-tAqaUW9c2m5tTblh .crit0,#mermaid-svg-tAqaUW9c2m5tTblh .crit1,#mermaid-svg-tAqaUW9c2m5tTblh .crit2,#mermaid-svg-tAqaUW9c2m5tTblh .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-tAqaUW9c2m5tTblh .activeCrit0,#mermaid-svg-tAqaUW9c2m5tTblh .activeCrit1,#mermaid-svg-tAqaUW9c2m5tTblh .activeCrit2,#mermaid-svg-tAqaUW9c2m5tTblh .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-tAqaUW9c2m5tTblh .doneCrit0,#mermaid-svg-tAqaUW9c2m5tTblh .doneCrit1,#mermaid-svg-tAqaUW9c2m5tTblh .doneCrit2,#mermaid-svg-tAqaUW9c2m5tTblh .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-tAqaUW9c2m5tTblh .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-tAqaUW9c2m5tTblh .milestoneText{font-style:italic}#mermaid-svg-tAqaUW9c2m5tTblh .doneCritText0,#mermaid-svg-tAqaUW9c2m5tTblh .doneCritText1,#mermaid-svg-tAqaUW9c2m5tTblh .doneCritText2,#mermaid-svg-tAqaUW9c2m5tTblh .doneCritText3{fill:#000 !important}#mermaid-svg-tAqaUW9c2m5tTblh .activeCritText0,#mermaid-svg-tAqaUW9c2m5tTblh .activeCritText1,#mermaid-svg-tAqaUW9c2m5tTblh .activeCritText2,#mermaid-svg-tAqaUW9c2m5tTblh .activeCritText3{fill:#000 !important}#mermaid-svg-tAqaUW9c2m5tTblh .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-tAqaUW9c2m5tTblh g.classGroup text .title{font-weight:bolder}#mermaid-svg-tAqaUW9c2m5tTblh g.clickable{cursor:pointer}#mermaid-svg-tAqaUW9c2m5tTblh g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-tAqaUW9c2m5tTblh g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-tAqaUW9c2m5tTblh .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-tAqaUW9c2m5tTblh .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-tAqaUW9c2m5tTblh .dashed-line{stroke-dasharray:3}#mermaid-svg-tAqaUW9c2m5tTblh #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh .commit-id,#mermaid-svg-tAqaUW9c2m5tTblh .commit-msg,#mermaid-svg-tAqaUW9c2m5tTblh .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-tAqaUW9c2m5tTblh g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-tAqaUW9c2m5tTblh g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-tAqaUW9c2m5tTblh g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-tAqaUW9c2m5tTblh .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-tAqaUW9c2m5tTblh .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-tAqaUW9c2m5tTblh .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-tAqaUW9c2m5tTblh .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-tAqaUW9c2m5tTblh .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-tAqaUW9c2m5tTblh .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-tAqaUW9c2m5tTblh .edgeLabel text{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-tAqaUW9c2m5tTblh .node circle.state-start{fill:black;stroke:black}#mermaid-svg-tAqaUW9c2m5tTblh .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-tAqaUW9c2m5tTblh #statediagram-barbEnd{fill:#9370db}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-state .divider{stroke:#9370db}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-tAqaUW9c2m5tTblh .note-edge{stroke-dasharray:5}#mermaid-svg-tAqaUW9c2m5tTblh .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-tAqaUW9c2m5tTblh .error-icon{fill:#522}#mermaid-svg-tAqaUW9c2m5tTblh .error-text{fill:#522;stroke:#522}#mermaid-svg-tAqaUW9c2m5tTblh .edge-thickness-normal{stroke-width:2px}#mermaid-svg-tAqaUW9c2m5tTblh .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-tAqaUW9c2m5tTblh .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-tAqaUW9c2m5tTblh .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-tAqaUW9c2m5tTblh .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-tAqaUW9c2m5tTblh .marker{fill:#333}#mermaid-svg-tAqaUW9c2m5tTblh .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-tAqaUW9c2m5tTblh {color: rgba(0, 0, 0, 0.75);font: ;}DogmakeSound() //bark()bark()AnimalmakeSound()CatmakeSound() //meow()meow()

针对实现编程:

Dog *d = new Dog();
d->bark();

针对接口/超类型编程:

Animal *animal = new Dog();
animal->makeSound();

知道对象是 Dog,但可以动态地使用 Animal 进行调用。

更好的是,与其将子类型的实例化 (例如 new Dog()) 硬编码到代码中,不如在运行时赋值具体的实现对象

a = getAnimal();
a->makeSound();

不知道实际的 Animal 子类型,只关心它知道如何正确进行 makeSound() 的动作。

实现鸭子的行为

两个接口 FlyBehavior 和 QuackBehavior,以及它们对应的实现每个具体行为的类。

#mermaid-svg-F86rJigCgtn8Sw9k .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-F86rJigCgtn8Sw9k .label text{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .node rect,#mermaid-svg-F86rJigCgtn8Sw9k .node circle,#mermaid-svg-F86rJigCgtn8Sw9k .node ellipse,#mermaid-svg-F86rJigCgtn8Sw9k .node polygon,#mermaid-svg-F86rJigCgtn8Sw9k .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-F86rJigCgtn8Sw9k .node .label{text-align:center;fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .node.clickable{cursor:pointer}#mermaid-svg-F86rJigCgtn8Sw9k .arrowheadPath{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-F86rJigCgtn8Sw9k .flowchart-link{stroke:#333;fill:none}#mermaid-svg-F86rJigCgtn8Sw9k .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-F86rJigCgtn8Sw9k .edgeLabel rect{opacity:0.9}#mermaid-svg-F86rJigCgtn8Sw9k .edgeLabel span{color:#333}#mermaid-svg-F86rJigCgtn8Sw9k .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-F86rJigCgtn8Sw9k .cluster text{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-F86rJigCgtn8Sw9k .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-F86rJigCgtn8Sw9k text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-F86rJigCgtn8Sw9k .actor-line{stroke:grey}#mermaid-svg-F86rJigCgtn8Sw9k .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-F86rJigCgtn8Sw9k .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-F86rJigCgtn8Sw9k #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-F86rJigCgtn8Sw9k .sequenceNumber{fill:#fff}#mermaid-svg-F86rJigCgtn8Sw9k #sequencenumber{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k #crosshead path{fill:#333;stroke:#333}#mermaid-svg-F86rJigCgtn8Sw9k .messageText{fill:#333;stroke:#333}#mermaid-svg-F86rJigCgtn8Sw9k .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-F86rJigCgtn8Sw9k .labelText,#mermaid-svg-F86rJigCgtn8Sw9k .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-F86rJigCgtn8Sw9k .loopText,#mermaid-svg-F86rJigCgtn8Sw9k .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-F86rJigCgtn8Sw9k .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-F86rJigCgtn8Sw9k .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-F86rJigCgtn8Sw9k .noteText,#mermaid-svg-F86rJigCgtn8Sw9k .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-F86rJigCgtn8Sw9k .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-F86rJigCgtn8Sw9k .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-F86rJigCgtn8Sw9k .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-F86rJigCgtn8Sw9k .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .section{stroke:none;opacity:0.2}#mermaid-svg-F86rJigCgtn8Sw9k .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-F86rJigCgtn8Sw9k .section2{fill:#fff400}#mermaid-svg-F86rJigCgtn8Sw9k .section1,#mermaid-svg-F86rJigCgtn8Sw9k .section3{fill:#fff;opacity:0.2}#mermaid-svg-F86rJigCgtn8Sw9k .sectionTitle0{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .sectionTitle1{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .sectionTitle2{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .sectionTitle3{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-F86rJigCgtn8Sw9k .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .grid path{stroke-width:0}#mermaid-svg-F86rJigCgtn8Sw9k .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-F86rJigCgtn8Sw9k .task{stroke-width:2}#mermaid-svg-F86rJigCgtn8Sw9k .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .taskText:not([font-size]){font-size:11px}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-F86rJigCgtn8Sw9k .task.clickable{cursor:pointer}#mermaid-svg-F86rJigCgtn8Sw9k .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F86rJigCgtn8Sw9k .taskText0,#mermaid-svg-F86rJigCgtn8Sw9k .taskText1,#mermaid-svg-F86rJigCgtn8Sw9k .taskText2,#mermaid-svg-F86rJigCgtn8Sw9k .taskText3{fill:#fff}#mermaid-svg-F86rJigCgtn8Sw9k .task0,#mermaid-svg-F86rJigCgtn8Sw9k .task1,#mermaid-svg-F86rJigCgtn8Sw9k .task2,#mermaid-svg-F86rJigCgtn8Sw9k .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutside0,#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutside2{fill:#000}#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutside1,#mermaid-svg-F86rJigCgtn8Sw9k .taskTextOutside3{fill:#000}#mermaid-svg-F86rJigCgtn8Sw9k .active0,#mermaid-svg-F86rJigCgtn8Sw9k .active1,#mermaid-svg-F86rJigCgtn8Sw9k .active2,#mermaid-svg-F86rJigCgtn8Sw9k .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-F86rJigCgtn8Sw9k .activeText0,#mermaid-svg-F86rJigCgtn8Sw9k .activeText1,#mermaid-svg-F86rJigCgtn8Sw9k .activeText2,#mermaid-svg-F86rJigCgtn8Sw9k .activeText3{fill:#000 !important}#mermaid-svg-F86rJigCgtn8Sw9k .done0,#mermaid-svg-F86rJigCgtn8Sw9k .done1,#mermaid-svg-F86rJigCgtn8Sw9k .done2,#mermaid-svg-F86rJigCgtn8Sw9k .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-F86rJigCgtn8Sw9k .doneText0,#mermaid-svg-F86rJigCgtn8Sw9k .doneText1,#mermaid-svg-F86rJigCgtn8Sw9k .doneText2,#mermaid-svg-F86rJigCgtn8Sw9k .doneText3{fill:#000 !important}#mermaid-svg-F86rJigCgtn8Sw9k .crit0,#mermaid-svg-F86rJigCgtn8Sw9k .crit1,#mermaid-svg-F86rJigCgtn8Sw9k .crit2,#mermaid-svg-F86rJigCgtn8Sw9k .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-F86rJigCgtn8Sw9k .activeCrit0,#mermaid-svg-F86rJigCgtn8Sw9k .activeCrit1,#mermaid-svg-F86rJigCgtn8Sw9k .activeCrit2,#mermaid-svg-F86rJigCgtn8Sw9k .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-F86rJigCgtn8Sw9k .doneCrit0,#mermaid-svg-F86rJigCgtn8Sw9k .doneCrit1,#mermaid-svg-F86rJigCgtn8Sw9k .doneCrit2,#mermaid-svg-F86rJigCgtn8Sw9k .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-F86rJigCgtn8Sw9k .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-F86rJigCgtn8Sw9k .milestoneText{font-style:italic}#mermaid-svg-F86rJigCgtn8Sw9k .doneCritText0,#mermaid-svg-F86rJigCgtn8Sw9k .doneCritText1,#mermaid-svg-F86rJigCgtn8Sw9k .doneCritText2,#mermaid-svg-F86rJigCgtn8Sw9k .doneCritText3{fill:#000 !important}#mermaid-svg-F86rJigCgtn8Sw9k .activeCritText0,#mermaid-svg-F86rJigCgtn8Sw9k .activeCritText1,#mermaid-svg-F86rJigCgtn8Sw9k .activeCritText2,#mermaid-svg-F86rJigCgtn8Sw9k .activeCritText3{fill:#000 !important}#mermaid-svg-F86rJigCgtn8Sw9k .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-F86rJigCgtn8Sw9k g.classGroup text .title{font-weight:bolder}#mermaid-svg-F86rJigCgtn8Sw9k g.clickable{cursor:pointer}#mermaid-svg-F86rJigCgtn8Sw9k g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-F86rJigCgtn8Sw9k g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-F86rJigCgtn8Sw9k .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-F86rJigCgtn8Sw9k .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-F86rJigCgtn8Sw9k .dashed-line{stroke-dasharray:3}#mermaid-svg-F86rJigCgtn8Sw9k #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k .commit-id,#mermaid-svg-F86rJigCgtn8Sw9k .commit-msg,#mermaid-svg-F86rJigCgtn8Sw9k .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-F86rJigCgtn8Sw9k g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-F86rJigCgtn8Sw9k g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-F86rJigCgtn8Sw9k g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-F86rJigCgtn8Sw9k .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-F86rJigCgtn8Sw9k .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-F86rJigCgtn8Sw9k .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-F86rJigCgtn8Sw9k .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-F86rJigCgtn8Sw9k .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-F86rJigCgtn8Sw9k .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-F86rJigCgtn8Sw9k .edgeLabel text{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F86rJigCgtn8Sw9k .node circle.state-start{fill:black;stroke:black}#mermaid-svg-F86rJigCgtn8Sw9k .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-F86rJigCgtn8Sw9k #statediagram-barbEnd{fill:#9370db}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-state .divider{stroke:#9370db}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-F86rJigCgtn8Sw9k .note-edge{stroke-dasharray:5}#mermaid-svg-F86rJigCgtn8Sw9k .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-F86rJigCgtn8Sw9k .error-icon{fill:#522}#mermaid-svg-F86rJigCgtn8Sw9k .error-text{fill:#522;stroke:#522}#mermaid-svg-F86rJigCgtn8Sw9k .edge-thickness-normal{stroke-width:2px}#mermaid-svg-F86rJigCgtn8Sw9k .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-F86rJigCgtn8Sw9k .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-F86rJigCgtn8Sw9k .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-F86rJigCgtn8Sw9k .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-F86rJigCgtn8Sw9k .marker{fill:#333}#mermaid-svg-F86rJigCgtn8Sw9k .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-F86rJigCgtn8Sw9k {color: rgba(0, 0, 0, 0.75);font: ;}FlyWithWingsfly()«interface»FlyBehaviorfly()FlyNoWayfly()Quackquack()«interface»QuackBehaviorquack()Squeakquack()MuteQuackquack()

使用这种设计,对象的其他类型可以复用 fly 和 quack 行为,因为这些行为不再隐藏在 Duck 类中。
而且,可以添加新的行为,而无需修改任何现有的行为类,也不会影响到任何使用 fly 行为的 Duck 类。

整合鸭子的行为

关键在于,Duck 现在将委托 (delegate) 其飞行和呱呱叫行为,而不是使用 Duck 类 (或子类) 中定义的 fly 和 quack 方法。

做法:

  1. 首先,在 Duck 类中添加两个变量 flyBehavior 和 quackBehavior,它们被声明为接口类型。每个鸭子对象都将多态设置这些变量,以在运行时引用其想要的特定行为类型 (如 FlyWithWings)。
    从 Duck 类 (和所有子类) 中删除 fly() 和 quack() 方法,因为这些行为已被移到了 FlyBehavior 和 QuackBehavior 类中。
    用两种类似的方法 performDly() 和 performQuack() 替换 Duck 类中的 fly() 和 quack()。
#mermaid-svg-E98P9jtUOY1g0S4V .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-E98P9jtUOY1g0S4V .label text{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .node rect,#mermaid-svg-E98P9jtUOY1g0S4V .node circle,#mermaid-svg-E98P9jtUOY1g0S4V .node ellipse,#mermaid-svg-E98P9jtUOY1g0S4V .node polygon,#mermaid-svg-E98P9jtUOY1g0S4V .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-E98P9jtUOY1g0S4V .node .label{text-align:center;fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .node.clickable{cursor:pointer}#mermaid-svg-E98P9jtUOY1g0S4V .arrowheadPath{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-E98P9jtUOY1g0S4V .flowchart-link{stroke:#333;fill:none}#mermaid-svg-E98P9jtUOY1g0S4V .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-E98P9jtUOY1g0S4V .edgeLabel rect{opacity:0.9}#mermaid-svg-E98P9jtUOY1g0S4V .edgeLabel span{color:#333}#mermaid-svg-E98P9jtUOY1g0S4V .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-E98P9jtUOY1g0S4V .cluster text{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-E98P9jtUOY1g0S4V .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-E98P9jtUOY1g0S4V text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-E98P9jtUOY1g0S4V .actor-line{stroke:grey}#mermaid-svg-E98P9jtUOY1g0S4V .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-E98P9jtUOY1g0S4V .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-E98P9jtUOY1g0S4V #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-E98P9jtUOY1g0S4V .sequenceNumber{fill:#fff}#mermaid-svg-E98P9jtUOY1g0S4V #sequencenumber{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V #crosshead path{fill:#333;stroke:#333}#mermaid-svg-E98P9jtUOY1g0S4V .messageText{fill:#333;stroke:#333}#mermaid-svg-E98P9jtUOY1g0S4V .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-E98P9jtUOY1g0S4V .labelText,#mermaid-svg-E98P9jtUOY1g0S4V .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-E98P9jtUOY1g0S4V .loopText,#mermaid-svg-E98P9jtUOY1g0S4V .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-E98P9jtUOY1g0S4V .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-E98P9jtUOY1g0S4V .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-E98P9jtUOY1g0S4V .noteText,#mermaid-svg-E98P9jtUOY1g0S4V .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-E98P9jtUOY1g0S4V .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-E98P9jtUOY1g0S4V .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-E98P9jtUOY1g0S4V .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-E98P9jtUOY1g0S4V .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .section{stroke:none;opacity:0.2}#mermaid-svg-E98P9jtUOY1g0S4V .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-E98P9jtUOY1g0S4V .section2{fill:#fff400}#mermaid-svg-E98P9jtUOY1g0S4V .section1,#mermaid-svg-E98P9jtUOY1g0S4V .section3{fill:#fff;opacity:0.2}#mermaid-svg-E98P9jtUOY1g0S4V .sectionTitle0{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .sectionTitle1{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .sectionTitle2{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .sectionTitle3{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-E98P9jtUOY1g0S4V .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .grid path{stroke-width:0}#mermaid-svg-E98P9jtUOY1g0S4V .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-E98P9jtUOY1g0S4V .task{stroke-width:2}#mermaid-svg-E98P9jtUOY1g0S4V .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .taskText:not([font-size]){font-size:11px}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-E98P9jtUOY1g0S4V .task.clickable{cursor:pointer}#mermaid-svg-E98P9jtUOY1g0S4V .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-E98P9jtUOY1g0S4V .taskText0,#mermaid-svg-E98P9jtUOY1g0S4V .taskText1,#mermaid-svg-E98P9jtUOY1g0S4V .taskText2,#mermaid-svg-E98P9jtUOY1g0S4V .taskText3{fill:#fff}#mermaid-svg-E98P9jtUOY1g0S4V .task0,#mermaid-svg-E98P9jtUOY1g0S4V .task1,#mermaid-svg-E98P9jtUOY1g0S4V .task2,#mermaid-svg-E98P9jtUOY1g0S4V .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutside0,#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutside2{fill:#000}#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutside1,#mermaid-svg-E98P9jtUOY1g0S4V .taskTextOutside3{fill:#000}#mermaid-svg-E98P9jtUOY1g0S4V .active0,#mermaid-svg-E98P9jtUOY1g0S4V .active1,#mermaid-svg-E98P9jtUOY1g0S4V .active2,#mermaid-svg-E98P9jtUOY1g0S4V .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-E98P9jtUOY1g0S4V .activeText0,#mermaid-svg-E98P9jtUOY1g0S4V .activeText1,#mermaid-svg-E98P9jtUOY1g0S4V .activeText2,#mermaid-svg-E98P9jtUOY1g0S4V .activeText3{fill:#000 !important}#mermaid-svg-E98P9jtUOY1g0S4V .done0,#mermaid-svg-E98P9jtUOY1g0S4V .done1,#mermaid-svg-E98P9jtUOY1g0S4V .done2,#mermaid-svg-E98P9jtUOY1g0S4V .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-E98P9jtUOY1g0S4V .doneText0,#mermaid-svg-E98P9jtUOY1g0S4V .doneText1,#mermaid-svg-E98P9jtUOY1g0S4V .doneText2,#mermaid-svg-E98P9jtUOY1g0S4V .doneText3{fill:#000 !important}#mermaid-svg-E98P9jtUOY1g0S4V .crit0,#mermaid-svg-E98P9jtUOY1g0S4V .crit1,#mermaid-svg-E98P9jtUOY1g0S4V .crit2,#mermaid-svg-E98P9jtUOY1g0S4V .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-E98P9jtUOY1g0S4V .activeCrit0,#mermaid-svg-E98P9jtUOY1g0S4V .activeCrit1,#mermaid-svg-E98P9jtUOY1g0S4V .activeCrit2,#mermaid-svg-E98P9jtUOY1g0S4V .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-E98P9jtUOY1g0S4V .doneCrit0,#mermaid-svg-E98P9jtUOY1g0S4V .doneCrit1,#mermaid-svg-E98P9jtUOY1g0S4V .doneCrit2,#mermaid-svg-E98P9jtUOY1g0S4V .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-E98P9jtUOY1g0S4V .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-E98P9jtUOY1g0S4V .milestoneText{font-style:italic}#mermaid-svg-E98P9jtUOY1g0S4V .doneCritText0,#mermaid-svg-E98P9jtUOY1g0S4V .doneCritText1,#mermaid-svg-E98P9jtUOY1g0S4V .doneCritText2,#mermaid-svg-E98P9jtUOY1g0S4V .doneCritText3{fill:#000 !important}#mermaid-svg-E98P9jtUOY1g0S4V .activeCritText0,#mermaid-svg-E98P9jtUOY1g0S4V .activeCritText1,#mermaid-svg-E98P9jtUOY1g0S4V .activeCritText2,#mermaid-svg-E98P9jtUOY1g0S4V .activeCritText3{fill:#000 !important}#mermaid-svg-E98P9jtUOY1g0S4V .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-E98P9jtUOY1g0S4V g.classGroup text .title{font-weight:bolder}#mermaid-svg-E98P9jtUOY1g0S4V g.clickable{cursor:pointer}#mermaid-svg-E98P9jtUOY1g0S4V g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-E98P9jtUOY1g0S4V g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-E98P9jtUOY1g0S4V .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-E98P9jtUOY1g0S4V .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-E98P9jtUOY1g0S4V .dashed-line{stroke-dasharray:3}#mermaid-svg-E98P9jtUOY1g0S4V #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V .commit-id,#mermaid-svg-E98P9jtUOY1g0S4V .commit-msg,#mermaid-svg-E98P9jtUOY1g0S4V .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-E98P9jtUOY1g0S4V g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-E98P9jtUOY1g0S4V g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-E98P9jtUOY1g0S4V g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-E98P9jtUOY1g0S4V .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-E98P9jtUOY1g0S4V .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-E98P9jtUOY1g0S4V .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-E98P9jtUOY1g0S4V .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-E98P9jtUOY1g0S4V .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-E98P9jtUOY1g0S4V .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-E98P9jtUOY1g0S4V .edgeLabel text{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-E98P9jtUOY1g0S4V .node circle.state-start{fill:black;stroke:black}#mermaid-svg-E98P9jtUOY1g0S4V .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-E98P9jtUOY1g0S4V #statediagram-barbEnd{fill:#9370db}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-state .divider{stroke:#9370db}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-E98P9jtUOY1g0S4V .note-edge{stroke-dasharray:5}#mermaid-svg-E98P9jtUOY1g0S4V .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-E98P9jtUOY1g0S4V .error-icon{fill:#522}#mermaid-svg-E98P9jtUOY1g0S4V .error-text{fill:#522;stroke:#522}#mermaid-svg-E98P9jtUOY1g0S4V .edge-thickness-normal{stroke-width:2px}#mermaid-svg-E98P9jtUOY1g0S4V .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-E98P9jtUOY1g0S4V .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-E98P9jtUOY1g0S4V .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-E98P9jtUOY1g0S4V .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-E98P9jtUOY1g0S4V .marker{fill:#333}#mermaid-svg-E98P9jtUOY1g0S4V .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-E98P9jtUOY1g0S4V {color: rgba(0, 0, 0, 0.75);font: ;}Duck#flyBehavior : FlyBehavior#quackBehavior : QuackBehavior+performQuack()+swim()+display()+performFly()
  1. 现在,实现 performQuack()。
    为了执行呱呱叫动作,Duck 只需允许 quackBehavior 引用的对象为它呱呱叫。
    在下面这段代码中,我们不关心对象的类型是什么,我们关心的是它知道如何 quack()!
class Duck {protected:std::unique_ptr<QuackBehavior> quackBehavior;// more
public:void performQuack() {// Duck对象本身并不处理呱呱叫行为,而是将这个行为委托给quackBehavior引用的对象quackBehavior->quack();}
};
  1. 如何设定 flyBehavior 和 quackBehavior 实例变量?以 MallardDuck 类为例:
class MallardDuck : public Duck {public:MallardDuck() {quackBehavior = std::unique_ptr<QuackBehavior>(new Quack());flyBehavior = std::unique_ptr<FlyBehavior>(new FlyWithWings());}void display() const {std::cout << "I'm a real Mallard duck" << std::endl;}
};

当 MallardDuck 被实例化时,其构造函数将 MallardDuck 的继承的 quackBehavior 实例变量初始化为 Quack 类型 (QuackBehavior 的具体实现类) 的新实例。

测试 Duck 的代码

// Duck.h
#include <iostream>
#include <memory>
#include "FlyBehavior"
#include "QuackBehavior"class Duck {protected:std::unique_ptr<FlyBehavior> flyBehavior;std::unique_ptr<QuackBehavior> quackBehavior;public:Duck() { }virtual void display() const = 0;void performFly() const {flyBehavior->fly();}void performQuack() const {quackBehavior->quack();}void swim() const {std::cout << "All ducks float, even decoys!" << std::endl;}
};class MallardDuck : public Duck {public:MallardDuck() {quackBehavior = std::unique_ptr<QuackBehavior>(new Quack());flyBehavior = std::unique_ptr<FlyBehavior>(new FlyWithWings());}void display() const {std::cout << "I'm a real Mallard duck" << std::endl;}
};****************************************************************************
// FlyBehavior.h
#include <iostream>
#include <memory>class FlyBehavior {public:virtual void fly () const = 0;
};class FlyWithWings : public FlyBehavior {public:void fly () const {std::cout << "I'm flying!!" << std::endl;}
};class FlyNoWay : public FlyBehavior {public:void fly () const {std::cout << "I can't fly" << std::endl;}
};****************************************************************************
// QuackBehavior.h
#include <iostream>
#include <memory>class QuackBehavior {public:virtual void quack() const = 0;
};class Quack : public QuackBehavior {public:void quack () const {std::cout << "Quack" << std::endl;}
};class MuteQuack : public QuackBehavior {public:void quack () const {std::cout << "<< Silence >>" << std::endl;}
};class Squeak : public QuackBehavior {public:void quack () const {std::cout << "Squeak" << std::endl;}
};****************************************************************************
// main.cpp
#include <iostream>
#include <memory>
#include "Duck.h"
#include "FlyBehavior.h"
#include "QuackBehavior.h"int main() {std::unique_ptr<MallardDuck> mallard(new MallardDuck());mallard->performQuack();mallard->performFly();system("pause");return 0;
}

运行代码:

动态设定行为

可以通过鸭子子类上的设定方法来设定鸭子的行为类型,而不只是通过在鸭子的构造函数中实例化鸭子的行为类型。

  1. 在 Duck 类中,添加两个方法。
    可以随时调用下面两个方法改变鸭子的行为。
 public: void setFlyBehavior(FlyBehavior* fb) {flyBehavior = std::unique_ptr<FlyBehavior>(fb);}public: void setQuackBehavior(QuackBehavior* qb) {quackBehavior = std::unique_ptr<QuackBehavior>(qb);}
  1. 创建一个新的 Duck 类型 ModelDuck。
class ModelDuck : public Duck {public:ModelDuck() {quackBehavior = std::unique_ptr<QuackBehavior>(new Quack());flyBehavior = std::unique_ptr<FlyBehavior>(new FlyNoWay());   // 一开始,模型鸭是不会飞的}void display() const {std::cout << "I'm a model duck" << std::endl;}
};
  1. 创建一个新的 FlyBehavior 类型 FlyRocketPowered。
// 创建一个利用火箭动力飞行的行为
class FlyRocketPowered : public FlyBehavior {public:void fly () const {std::cout << "I'm flying with a rocket" << std::endl;}
};
  1. 在 main 函数中增加 ModelDuck,并使模型鸭具有火箭动力。
 std::unique_ptr<ModelDuck> model(new ModelDuck());model->performFly(); model->setFlyBehavior(new FlyRocketPowered());model->performFly();

运行程序:

封装行为的大局观

现在看看整体的格局。下面是整个重新设计的类结构。

注意,现在开始对事物的描述有所不同。不再将鸭子行为视为一组行为 (set of behaviors),而是将它们视为一族算法 (family of behaviors)。想想看:在 SimUDuck 设计中,算法代表鸭子会做的事情 (呱呱叫或飞行的不同方式),这样的技术可以很容易地用于一组类,用来实现计算不同州的销售税金。

注意类之间的关系 (relationships)。
在类图中的每个箭头上标上适当的关系:IS-A (是一个)、HAS-A (有一个) 和 IMPLEMENTS (实现)。

#mermaid-svg-XiorGtiDvgZewx9m .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-XiorGtiDvgZewx9m .label text{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .node rect,#mermaid-svg-XiorGtiDvgZewx9m .node circle,#mermaid-svg-XiorGtiDvgZewx9m .node ellipse,#mermaid-svg-XiorGtiDvgZewx9m .node polygon,#mermaid-svg-XiorGtiDvgZewx9m .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-XiorGtiDvgZewx9m .node .label{text-align:center;fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .node.clickable{cursor:pointer}#mermaid-svg-XiorGtiDvgZewx9m .arrowheadPath{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-XiorGtiDvgZewx9m .flowchart-link{stroke:#333;fill:none}#mermaid-svg-XiorGtiDvgZewx9m .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-XiorGtiDvgZewx9m .edgeLabel rect{opacity:0.9}#mermaid-svg-XiorGtiDvgZewx9m .edgeLabel span{color:#333}#mermaid-svg-XiorGtiDvgZewx9m .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-XiorGtiDvgZewx9m .cluster text{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-XiorGtiDvgZewx9m .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-XiorGtiDvgZewx9m text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-XiorGtiDvgZewx9m .actor-line{stroke:grey}#mermaid-svg-XiorGtiDvgZewx9m .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-XiorGtiDvgZewx9m .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-XiorGtiDvgZewx9m #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-XiorGtiDvgZewx9m .sequenceNumber{fill:#fff}#mermaid-svg-XiorGtiDvgZewx9m #sequencenumber{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m #crosshead path{fill:#333;stroke:#333}#mermaid-svg-XiorGtiDvgZewx9m .messageText{fill:#333;stroke:#333}#mermaid-svg-XiorGtiDvgZewx9m .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-XiorGtiDvgZewx9m .labelText,#mermaid-svg-XiorGtiDvgZewx9m .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-XiorGtiDvgZewx9m .loopText,#mermaid-svg-XiorGtiDvgZewx9m .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-XiorGtiDvgZewx9m .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-XiorGtiDvgZewx9m .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-XiorGtiDvgZewx9m .noteText,#mermaid-svg-XiorGtiDvgZewx9m .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-XiorGtiDvgZewx9m .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-XiorGtiDvgZewx9m .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-XiorGtiDvgZewx9m .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-XiorGtiDvgZewx9m .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .section{stroke:none;opacity:0.2}#mermaid-svg-XiorGtiDvgZewx9m .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-XiorGtiDvgZewx9m .section2{fill:#fff400}#mermaid-svg-XiorGtiDvgZewx9m .section1,#mermaid-svg-XiorGtiDvgZewx9m .section3{fill:#fff;opacity:0.2}#mermaid-svg-XiorGtiDvgZewx9m .sectionTitle0{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .sectionTitle1{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .sectionTitle2{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .sectionTitle3{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-XiorGtiDvgZewx9m .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .grid path{stroke-width:0}#mermaid-svg-XiorGtiDvgZewx9m .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-XiorGtiDvgZewx9m .task{stroke-width:2}#mermaid-svg-XiorGtiDvgZewx9m .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .taskText:not([font-size]){font-size:11px}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-XiorGtiDvgZewx9m .task.clickable{cursor:pointer}#mermaid-svg-XiorGtiDvgZewx9m .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XiorGtiDvgZewx9m .taskText0,#mermaid-svg-XiorGtiDvgZewx9m .taskText1,#mermaid-svg-XiorGtiDvgZewx9m .taskText2,#mermaid-svg-XiorGtiDvgZewx9m .taskText3{fill:#fff}#mermaid-svg-XiorGtiDvgZewx9m .task0,#mermaid-svg-XiorGtiDvgZewx9m .task1,#mermaid-svg-XiorGtiDvgZewx9m .task2,#mermaid-svg-XiorGtiDvgZewx9m .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutside0,#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutside2{fill:#000}#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutside1,#mermaid-svg-XiorGtiDvgZewx9m .taskTextOutside3{fill:#000}#mermaid-svg-XiorGtiDvgZewx9m .active0,#mermaid-svg-XiorGtiDvgZewx9m .active1,#mermaid-svg-XiorGtiDvgZewx9m .active2,#mermaid-svg-XiorGtiDvgZewx9m .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-XiorGtiDvgZewx9m .activeText0,#mermaid-svg-XiorGtiDvgZewx9m .activeText1,#mermaid-svg-XiorGtiDvgZewx9m .activeText2,#mermaid-svg-XiorGtiDvgZewx9m .activeText3{fill:#000 !important}#mermaid-svg-XiorGtiDvgZewx9m .done0,#mermaid-svg-XiorGtiDvgZewx9m .done1,#mermaid-svg-XiorGtiDvgZewx9m .done2,#mermaid-svg-XiorGtiDvgZewx9m .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-XiorGtiDvgZewx9m .doneText0,#mermaid-svg-XiorGtiDvgZewx9m .doneText1,#mermaid-svg-XiorGtiDvgZewx9m .doneText2,#mermaid-svg-XiorGtiDvgZewx9m .doneText3{fill:#000 !important}#mermaid-svg-XiorGtiDvgZewx9m .crit0,#mermaid-svg-XiorGtiDvgZewx9m .crit1,#mermaid-svg-XiorGtiDvgZewx9m .crit2,#mermaid-svg-XiorGtiDvgZewx9m .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-XiorGtiDvgZewx9m .activeCrit0,#mermaid-svg-XiorGtiDvgZewx9m .activeCrit1,#mermaid-svg-XiorGtiDvgZewx9m .activeCrit2,#mermaid-svg-XiorGtiDvgZewx9m .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-XiorGtiDvgZewx9m .doneCrit0,#mermaid-svg-XiorGtiDvgZewx9m .doneCrit1,#mermaid-svg-XiorGtiDvgZewx9m .doneCrit2,#mermaid-svg-XiorGtiDvgZewx9m .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-XiorGtiDvgZewx9m .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-XiorGtiDvgZewx9m .milestoneText{font-style:italic}#mermaid-svg-XiorGtiDvgZewx9m .doneCritText0,#mermaid-svg-XiorGtiDvgZewx9m .doneCritText1,#mermaid-svg-XiorGtiDvgZewx9m .doneCritText2,#mermaid-svg-XiorGtiDvgZewx9m .doneCritText3{fill:#000 !important}#mermaid-svg-XiorGtiDvgZewx9m .activeCritText0,#mermaid-svg-XiorGtiDvgZewx9m .activeCritText1,#mermaid-svg-XiorGtiDvgZewx9m .activeCritText2,#mermaid-svg-XiorGtiDvgZewx9m .activeCritText3{fill:#000 !important}#mermaid-svg-XiorGtiDvgZewx9m .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-XiorGtiDvgZewx9m g.classGroup text .title{font-weight:bolder}#mermaid-svg-XiorGtiDvgZewx9m g.clickable{cursor:pointer}#mermaid-svg-XiorGtiDvgZewx9m g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-XiorGtiDvgZewx9m g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-XiorGtiDvgZewx9m .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-XiorGtiDvgZewx9m .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-XiorGtiDvgZewx9m .dashed-line{stroke-dasharray:3}#mermaid-svg-XiorGtiDvgZewx9m #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m .commit-id,#mermaid-svg-XiorGtiDvgZewx9m .commit-msg,#mermaid-svg-XiorGtiDvgZewx9m .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-XiorGtiDvgZewx9m g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-XiorGtiDvgZewx9m g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-XiorGtiDvgZewx9m g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-XiorGtiDvgZewx9m .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-XiorGtiDvgZewx9m .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-XiorGtiDvgZewx9m .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-XiorGtiDvgZewx9m .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-XiorGtiDvgZewx9m .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-XiorGtiDvgZewx9m .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-XiorGtiDvgZewx9m .edgeLabel text{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XiorGtiDvgZewx9m .node circle.state-start{fill:black;stroke:black}#mermaid-svg-XiorGtiDvgZewx9m .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-XiorGtiDvgZewx9m #statediagram-barbEnd{fill:#9370db}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-state .divider{stroke:#9370db}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-XiorGtiDvgZewx9m .note-edge{stroke-dasharray:5}#mermaid-svg-XiorGtiDvgZewx9m .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-XiorGtiDvgZewx9m .error-icon{fill:#522}#mermaid-svg-XiorGtiDvgZewx9m .error-text{fill:#522;stroke:#522}#mermaid-svg-XiorGtiDvgZewx9m .edge-thickness-normal{stroke-width:2px}#mermaid-svg-XiorGtiDvgZewx9m .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-XiorGtiDvgZewx9m .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-XiorGtiDvgZewx9m .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-XiorGtiDvgZewx9m .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-XiorGtiDvgZewx9m .marker{fill:#333}#mermaid-svg-XiorGtiDvgZewx9m .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-XiorGtiDvgZewx9m {color: rgba(0, 0, 0, 0.75);font: ;}Duck#flyBehavior : FlyBehavior#quackBehavior : QuackBehavior+swim()+display()+performQuack()+performFly()+setFlyBehavior()+setQuackBehavior()MallardDuckdisplay()RedheadDuckdisplay()RubberDuckdisplay()DecoyDuckdisplay()FlyWithWingsfly()«interface»FlyBehaviorfly()FlyNoWayfly()Quackquack()«interface»QuackBehaviorquack()Squeakquack()MuteQuackquack()

设计原则三

HAS-A 可能比 IS-A 更好

HAS-A 关系:每个鸭子有一个 FlyBehavior 和 QuackBehavior,可以将飞行和呱呱叫行为委托给它们。

将两个类像这样结合起来,就是组合 (composition)。鸭子获取行为不是通过继承行为,而是通过与适当的行为对象进行组合

这是一个很重要的技术,使用了下面的设计原则。

设计原则3:优先考虑组合,而非继承。

使用组合建立系统可以带来更大的灵活性。它不仅可以将算法族封装到它们自己的类的集合中,而且还可以在运行时改变行为,只要组合的对象实现了正确的行为接口即可。

策略模式

上面的应用程序使用了策略模式 (Strategy Pattern)。

策略模式定义了一族算法,将每个算法封装起来,并使它们之间可互相替换。策略模式使算法的变化可以独立于使用该算法的客户。

共享模式词汇的力量

设计模式为你提供了与其他开发人员共享的词汇表。掌握了这些词汇后,你可以更轻松地与其他开发人员进行交流。通过在模式级别进行思考,而不是在具体细节的对象级别进行思考,还可以提高你对架构的思考。

当你使用模式与他人沟通时,你做的不只是在与他人共享“行话”。

  • 共享的模式词汇是强有力的。当你使用模式与其他开发人员或团队交流时,你们交流的不只是模式名称,还是模式所代表的一整套质量、特性和约束。
    “使用策略模式来实现鸭子的各种行为。” 这告诉你,鸭子行为已封装到它自己的一组类中,可以被轻松地扩展和更改,甚至在需要时也可以在运行时进行更改。
  • 模式让你使用更少的话语表述更多的内容。当你在描述中使用模式时,其他开发人员会快速准确地了解你头脑中的设计。
  • 在模式级别进行交谈可以使你待“在设计中”的时间更长。讨论使用模式的软件系统使你可以将讨论保持在设计级别,而不必深入了解实现对象和类的具体细节。
  • 共享的词汇可以为你的开发团队提供强大的动力。精通设计模式的团队可以更快地行动,减少误解的空间。
  • 共享的词汇表鼓励更多的初级开发人员快速上手。初级开发人员仰赖经验丰富的开发人员。当高级开发人员使用设计模式时,初级开发人员也会开始学习它们。在你的组织中建立模式使用者的社区。

如何使用设计模式

我们都使用过现成的库和框架。我们使用它们,针对它们的API编写一些代码,将它们编译到我们的程序中。库和框架对开发模型大有帮助,我们可以选择组件并直接将其放入适当的位置。但是,它们不能帮助我们以更易于理解、更易于维护和更灵活的方式来构建应用程序。这就是设计模式的用武之地。

设计模式不会直接进入你的代码,而是会首先进入你的大脑。一旦你在大脑中装载了许多关于模式的运用知识,就可以开始将其应用于新设计,并在发现旧代码变得混乱没有灵活性时对其进行重新处理。

设计模式比库的等级更高。设计模式告诉我们如何构建类和对象来解决某个问题。

框架和库不是设计模式;它们提供特定的实现,可以应用到我们的代码中。有时,库和框架会在实现中使用模式设计。一旦理解了设计模式,你会更快地理解围绕着设计模式构建的API。

为什么要使用设计模式

知道抽象、继承和多态这些概念不会让你成为一个好的面向对象的设计者。设计大师考虑如何创建灵活的设计,它是可维护的,可以应对变化。

如果找不到设计模式怎么办?

构成模式的基础是一些面向对象的原理,当找不到适合的模式解决问题时,这些原理会为你提供帮助。

创建可维护的OO系统的秘诀之一就是思考它们将来如何变化,这些原则解决了这些问题。

设计工具箱内的工具

OO基础:抽象、封装、多态、继承

OO原则:

  • 将变化的部分封装起来
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程

OO模式:

  • 策略模式

要点:

  • 好的OO设计是可复用的、可扩充的、可维护的。
  • 模式是经过验证的面向对象的经验。
  • 模式不会为你提供代码,而是为你提供设计问题的通用解决方案。
  • 大多数模式和原则都应对软件变化问题。
  • 大多数模式都允许系统的某些部分的变化独立于所有其他部分。
  • 我们经常尝试取出系统中的变化部分,并将其封装。

【Head First 模式设计】目录

【Head First 模式设计】第1章 策略模式相关推荐

  1. 第 25 章 策略模式

    第 25 章 策略模式 1.编写鸭子项目 编写鸭子项目,具体要求如下: 有各种鸭子(比如野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如叫.飞行等) 显示鸭子的信息 2.传统方案解决鸭子问题 传统方案解决 ...

  2. 象棋子 设计模式_通过设计国际象棋游戏了解策略模式

    象棋子 设计模式 今天,我们将借助一个示例来尝试了解策略模式. 我们将考虑的示例是国际象棋游戏. 这里的目的是解释策略模式,而不是构建全面的国际象棋游戏解决方案. 策略模式:策略模式被称为行为模式–用 ...

  3. java并发编程:设计原则与模式_java编程设计模式一——策略模式

    定义: 策略模式定义了算法族,分别封装起来,让它们之间相互替代.此模式让算法的变化独立于使用算法的客户. 问题描述: 建立一个鸭子Duck的父类,它有很多子类,Duck都会游泳,但是有鸭子会飞,有的鸭 ...

  4. 第1章 策略模式【StrategyPattern】

    刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到最后是周瑜陪了夫人又折兵呀,那咱们先看看这个场景是什么样子的. 先说这个场景 ...

  5. 大话设计模式 第二章 策略模式购物车价格查询

    策略模式定义 定义一系列功能 把它们一个个封装起来 并使它们可以相互替换 提供统一的入口访问包装的功能 问题 添加商品和优惠券到购物车后查询价格 思考 要想获取购物车的支付价格 需要经过所有的优惠券优 ...

  6. 第 1 章 策略模式

    <?php header("Content-type: text/html; charset=UTF-8"); /** * 策略模式的好处就是:体现了高内聚低耦合的特性 */ ...

  7. java 策略模式会员_七:策略模式(不同等级会员打折算法)

    定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化: 下面给出策略模式的类图,引自百度百科. 策略模式在LZ第一次接触到的时 ...

  8. IT行业热点商业模式随笔第七章——商业模式创新规律

    前言: 第一章:商业模式面面观 第二章:长尾商业模式 第三章:免费商业模式 第四章:平台商业模式 第五章:开放式商业模式 第六章:完美商业模式--印钞机 第七章:商业模式创新规律 第七章:商业模式创新 ...

  9. java8 策略模式_Java 8中的策略模式

    java8 策略模式 这是两个有关如何使用Java 8功能样式以及Cyclops模式匹配和Hamcrest库来实现策略模式设计的示例. PrintDependingOnInput方法是一种策略,该策略 ...

最新文章

  1. Go 学习笔记(16)— 函数(02)[函数签名、有名函数、匿名函数、调用匿名函数、匿名函数赋值给变量、匿名函数做回调函数]
  2. python中set集合如何决定是否重复?
  3. if函数 字体自动标红_发喜糖!REPT函数和图表订婚了~~
  4. mybatis是否接受运算符参数化
  5. OSI七层、TCP/IP五层、UDP、TCP的socket编程(服务端及客户端)、字节序转换、多进程以及多线程服务端的实现
  6. 题解【luogu2045 方格取数游戏加强版】
  7. java比身高怎么做_D3 Y比例,y对比身高?
  8. windows批量重命名
  9. 预测模型| 2. Nomogram文献抄读 (2): 如何建立和解读癌症预后列线图
  10. angular ng-show中表达式的写法
  11. 报错:WebMvcConfigurer.class cannot be opened because it does not exist
  12. redis基础命令和数据操作命令学习笔记
  13. MySQL中出现Duplicate entry 'XXX' for key 'PRIMARY'解决方案
  14. 计算机原理论文2000字,计算机原理论文_计算机论文3000字_对计算机的认识论文...
  15. arch firefox
  16. 系统服务器性能巡检报告,pc服务器巡检报告
  17. 北邮计科院导师简况2009-09-27 14:13:38
  18. 搜索100亿网页 雅虎搜索放言技术已超百度
  19. C#绩效管理系统(二)导航栏和用户管理窗口的基本实现
  20. 软件工程专业电商网站毕业论文答辩实录(基于SSM+VUE前后端分离的 “依伴汉服”网)

热门文章

  1. 大厂代码规范及个人本学期的代码规范
  2. SQL Server Management Studio(SMSS)删除连接记录
  3. MacBook Air移动硬盘分区
  4. Unity 协程的原理
  5. [hihocoder]1238 : Total Highway Distance
  6. easyui datagrid th标签列数字保留2位小数
  7. Lined List 链表总结 Reverse链表 - 反转(python) leetcode 206 92
  8. 如何修改安卓应用图标和程序名称
  9. Qt5.14.2下载与安装
  10. SSH和文件传输(SCP)