軟體實體(類別、模組、函式)應該對擴充開放,對修改關閉。
需求變更導致原始碼修改,引入 Bug 或需大規模迴歸測試。典型違反 OCP 程式碼:
class ChartDisplay {
public void display(String type) {
if ("pie".equals(type)) {
new PieChart().display();
} else if ("bar".equals(type)) {
new BarChart().display();
}
// 新增折線圖必須修改此方法 → 違反 OCP
}
}
AbstractChartChartDisplay 依賴抽象,透過 setChart() 注入具體實作// 抽象層
interface AbstractChart {
void display();
}
// 具體實作
class PieChart implements AbstractChart {
public void display() { System.out.println("顯示餅狀圖"); }
}
class BarChart implements AbstractChart {
public void display() { System.out.println("顯示長條圖"); }
}
class LineChart implements AbstractChart { // 新增折線圖,零修改既有程式碼
public void display() { System.out.println("顯示折線圖"); }
}
// 高層模組依賴抽象
class ChartDisplay {
private AbstractChart chart;
public void setChart(AbstractChart chart) {
this.chart = chart;
}
public void display() {
if (chart != null) chart.display();
}
}
// 客戶端組裝
public class Client {
public static void main(String[] args) {
ChartDisplay display = new ChartDisplay();
display.setChart(new PieChart()); // 可動態切換
display.display();
display.setChart(new LineChart()); // 新增類別無需修改 ChartDisplay
display.display();
}
}
OCP 是「總綱」,其餘五原則是「落地手段」:
遵守後五原則 → 自然滿足 OCP。OCP 可視為前五原則遵守程度的「綜合得分」。
interface 或 abstract class 定義穩定抽象層| 檢查點 | 符合 OCP 特徵 |
|---|---|
| 新增功能是否需修改既有類別? | 否(只需新增類別) |
| 是否針對介面/抽象類別編程? | 是 |
| 是否使用 DI/工廠/策略模式注入具體實作? | 是 |
| 配置檔調整能否替換行為? | 是 |
開閉原則不是「從不修改程式碼」,而是「將變化點封裝在可擴充的抽象體系中」。透過抽象化設計、依賴倒轉、策略模式等手段,讓系統在面對新需求時,只需「新增類別、調整配置」,即可實現功能擴充,最大程度保護既有資產穩定運行。