程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 詳細介紹開閉原則(OCP)

詳細介紹開閉原則(OCP)

編輯:關於C語言

開閉原則的意思是軟件實體應該對擴展開發,對修改關閉(Software entitIEs should be open for extension,but closed for modification)。實現開閉原則的途徑是抽象,將需要擴展的部分抽象出來,並留出擴展接口。打個比方,比如電腦機箱上有usb的插口,這些插口就是可擴展的部分,我們可以在這些usb插口上插上鼠標,鍵盤,U盤,還可以插上網銀的U盾等等。電腦硬件上對於usb接口的這個設計就是一個符合開閉原則的設計。

為什麼要遵循開閉原則呢?因為開閉原則可以使軟件系統更容易復用,更容易維護,當某個軟件實體,不適合了,我可以重新做另外一種實現,並將現有的實現替換掉。比如說統計個稅的算法發生了一些變化,我可以在不改變原有代碼的情況下,重新實現一個算法將原有的算法替換下來。比如說殺毒軟件,在出現一種新的病毒時,開發出一個查殺這種病毒的新模塊,可以只開發更新這個查殺模塊,而不需要改變原有系統的內容。

開閉原則這麼好,如何實現符合開閉原則的軟件系統呢?答案是抽象,將可能發生變化的功能點進行抽象,並留出變化的接口。設計模式中很多模式都可以幫我們實現開閉原則,個人的理解設計模式是對抽象用法的一種總結。

其實我們在項目已經為開閉原則做了一些工作了,比如說我們進行三層開發,將數據層抽象出來,並定義個數據處理的接口,我們可以通過新開發一個數據層把剛開始將數據存放到SQL Server中的實現,修改為將數據存放到my sql中的實現;我們將業務邏輯中的代碼從UI代碼中分離出來,這就為我們復用業務邏輯的代碼提供了可能,我們可以開發一個專門為手機使用的UI層出來,當用戶用手機訪問我們的系統時,智能的切換到手機UI層的代碼上去執行。

實現開閉原則的例子,其實我都不好意思自己舉例子了,因為我正在使用Office 2007寫這篇博客,在Office2007的快捷工具欄中就有一項是加載項,就是說Office 2007能將插件加載進來使用,如下圖所示:

圖一

Snagit在Word中添加了一個插件,這種插件技術就是一種遵循OCP的實現;再說我們整天使用的Visual Studio 它的可擴展程度更高,可以開發很多類型的工具對他進行擴展。

為了本文的完整性,我還是厚著臉皮,用重構的方式舉一個遵循開閉原則的微不足道的實現。

下面的舉例實現的場景是個稅的計算:我的第一個版本是這樣子的

  1. class Program   
  2. {   
  3. static void Main(string[] args)   
  4. {   
  5. float salary = 10000;   
  6. Console.WriteLine("收入是{0}的人應繳個稅是{1},",salary, GetTax(salary));   
  7. }   
  8. static float GetTax(float salary)   
  9. {   
  10. return (float)(salary * 0.03);   
  11. }   

這個版本中我未做任何抽象,直接調用靜態方法算了,可是一不小心開兩會了,個稅要調整了,於是個稅的算法要進行調整了,怎麼辦呢,因為要少繳稅,我很高興的就要來重構上面的代碼了,既然個稅的計算方法是一個變化的東西,我就把它抽象出來吧。

  1. class Program   
  2. {   
  3. static void Main(string[] args)   
  4. {   
  5. float salary = 10000;   
  6. Console.WriteLine("收入是{0}的人應繳個稅是{1},",salary, GetTax(salary));   
  7. }   
  8. static float GetTax(float salary)   
  9. {   
  10. ITaxCalculateStrategy strategy = GetTaxCalculateStrategy();   
  11. return strategy.GetTax(salary);   
  12. }   
  13. /// <summary>   
  14. /// 獲得應該使用的個稅計算方法   
  15. /// </summary>   
  16. /// <returns>個稅計算方法實現實例</returns>   
  17. static ITaxCalculateStrategy GetTaxCalculateStrategy() {   
  18. string typeName = ConfigurationManager.APPSettings["TaxCalculateStrategyType"];   
  19. if (string.IsNullOrEmpty(typeName))   
  20. throw new ConfigurationErrorsException("請配置TaxCalculateStrategyType");   
  21. Type type = Type.GetType(typeName);   
  22. if (type == null) throw new ConfigurationErrorsException("TaxCalculateStrategyType錯誤");   
  23. return (ITaxCalculateStrategy)Activator.CreateInstance(type);   
  24. }   
  25. }   
  26. /// <summary>   
  27. /// 定義個稅計算的接口   
  28. /// </summary>   
  29. public interface ITaxCalculateStrategy   
  30. {   
  31. float GetTax(float salary);   
  32. }   
  33. /// <summary>   
  34. /// 兩會前個稅計算辦法的實現   
  35. /// </summary>   
  36. public class TaxCalculateBefore2Conference : ITaxCalculateStrategy   
  37. {   
  38. float ITaxCalculateStrategy.GetTax(float salary)   
  39. {   
  40. return (float)(salary * 0.03);   
  41. }   
  42. }   
  43. /// <summary>   
  44. /// 兩會後個稅的計算方法   
  45. /// </summary>   
  46. public class TaxCalculateAfter2Conference:ITaxCalculateStrategy   
  47. {   
  48. float ITaxCalculateStrategy.GetTax(float salary)   
  49. {   
  50. return (float)(salary * 0.020);   
  51. }   

因為要少繳稅,所以我很愉快的重構了之前的代碼,可以轉眼兩會開完了,結果並非如我預期的個稅變化,咋辦呢?沒關系我們重新開發一個個稅計算方法,修改下配置就可以仍舊使用之前的個稅計算辦法了。

開閉原則實現的關鍵點在於抽象,也許我們剛開始不知道該把那部分抽象出來,但是這並不是問題,我們可以遵循簡單設計的原則,當變化來了的時候,再重構代碼,做到一種滿足開閉原則的設計。

切忌到處都抽象,如果到處都抽象就會導致系統過度設計,過度復雜。這反而是不利於系統的維護。完全的開閉原則是不可能實現的,所以請保持簡單設計,在需要的時候做符合開閉原則的設計。

通過本文對開閉原則的介紹,希望對你有幫助。

【編輯推薦】

  1. C#3.0中對象初始化器和集合初始化器
  2. C#.Net ArrayList的使用
  3. C#中 As 和強制轉換的總結
  4. 漫談C#開發中的ASP.Net頁生命周期
  5. 分享c#常用函數和方法集
【責任編輯:QiHappy TEL:(010)68476606】
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved