本文
開放封閉原則 Open-Close Principle(OCP)
定義
軟體設計原則,應該對擴展開放,對修改封閉。
甚麼意思呢?
- 1、對擴展開放 - 程式碼對於新增功能是透過新增程式碼進行。
- 2、對修改封閉 - 新增功能時不應該是更改現有程式碼。
那為甚麼要使用 OCP?
- 1、程式碼可維護性提高。
- 2、程式碼可擴展性提高。
- 3、程式碼可複用、靈活性高。
- 4、程式碼可測試性提高。
2020/09/08更新
寫完這篇跟同事討論過後決定要更改,一直發懶就放到現在,被迫要在進入下階段前先把前面要改的改完。
現在回頭看覺得當初為啥寫這例子怪怪的,回想起來才發現,原來我是為了避免使用到 DI 的觀念啊,但後來看了其他人寫的文章,用 DI 好像比較容易敘述這個概念…
所以就頭都要洗了,就先挖個坑吧。
我們來看一段例子,傳統汽車對於軟體硬體整合,還不夠靈活的時候,需要更改東西就需要把整台汽車拆開某些部分增加功能、每一次更改都是一項大工程。
public class 影音撥放器
{
public string 安裝()
{
return "安裝影音撥放器成功";
}
}
public class 自動導航裝置
{
public string 安裝()
{
return "安裝自動導航裝置成功";
}
}
public class 汽車
{
public string 安裝影音撥放器()
{
var 影音波放器 = new 影音撥放器();
return 影音波放器.安裝();
}
public string 安裝自動導航裝置()
{
var 自動導航裝置 = new 自動導航裝置();
return 自動導航裝置.安裝();
}
}
private static void Main(string[] args)
{
var 汽車 = new 汽車();
Console.WriteLine($"汽車:{汽車.安裝影音撥放器()}");
Console.WriteLine($"汽車:{汽車.安裝自動導航裝置()}");
}
這時候發現如果我們要在加個停車導引功能的時候,又需要再把車子拆開來安裝停車導引系統;這時候我們可以看看特斯拉的作法,一開始先把車子硬體都準備好,當你有需要增加功能時對特斯拉來說就只是更新軟體而已。
//更新軟體介面
public interface I更新軟體
{
public string 安裝(string 安裝項目)
{
return "";
}
}
//實作功能
public class 更新軟體 : I更新軟體
{
public string 安裝(string 安裝項目)
{
return($"安裝{安裝項目}成功");
}
}
public class 特斯拉
{
private readonly 更新軟體 _更新軟體;
public 特斯拉(更新軟體 更新軟體)
{
this._更新軟體 = 更新軟體;
}
public string 安裝影音撥放器()
{
return this._更新軟體.安裝("影音撥放器");
}
public string 安裝自動導航裝置()
{
return this._更新軟體.安裝("自動導航裝置");
}
public string 安裝停車導引系統()
{
return this._更新軟體.安裝("停車導引系統");
}
}
private static void Main(string[] args)
{
//今天Models想增加功能時,就可以透過更新軟體安裝想要的功能。
var ModelS = new 特斯拉(new 更新軟體());
Console.WriteLine(ModelS.安裝影音撥放器());
Console.WriteLine(ModelS.安裝自動導航裝置());
Console.WriteLine(ModelS.安裝停車導引系統());
}
這樣就可以透過更新軟體來增加自己想要的功能,未來想要增加新功能時,也不需要更改其他地方只要針對特斯拉這個類別做更新就可以,以此達到OCP精神。
這邊的更新軟體作法是使用了 DI,後續文章會在說明DI用法,想先了解的可以先點此Dependency Injection概念介紹