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

關於開閉原則的理解

編輯:.NET實例教程

開閉原則:設計一個模塊的時候,應當使這個模塊可以在不修改原有代碼的前提下被擴展。

這個原則是保證系統具有擴展性的基本原則。我理解有幾個要點:1、要能夠復用;2、擴展時只增加新方法、新類;3、不得不修改代碼時,修改的范圍必須是局部的、隱藏的;

通常變更有三種方式,一種是橫向變更,例如售票系統,原來只能售火車票,現在要可以售機票;第二種是縱向變更,例如在某個流程裡插入新活動或跳過活動;第三種是局部修改,就是原有功能的業務規則發生了變化。對於前兩種變更比較容易處理,只要在設計時注意抽象,通過接口、繼承、override或event即可擴充。對於第三種變更,估計要修改代碼了。雖然可以這樣分類,但實際上以上三種變更通常是同時發生的、相互交織的。

以庫存管理業務單據為例,有出庫單、入庫單、移庫單等。通常單據結構都很相似,包含頭表,行表,但個別字段有差異。新增一個單據,先在頭表插入一條記錄,然後在行表插入若干記錄。更新單據時,先更新頭表記錄,然後清空詞單據在行表裡的原有記錄,再插入新的行表記錄,刪除單據的過程也非常相似。此外,在單據增刪改時要記錄日志,在單據提交時,還要修改庫存。所有這些操作十分相似,可以抽象出來。

現在要設計一個單據處理通用業務類,負責單據暫存、修改、提交、刪除幾個基本業務,以及相關的日志和庫存操作。

1、分析
   單據操作: Save()/Submit()/Delete()/Log()/ChangeStock()
   相關數據: 頭表實體、行表實體集;與日志有關的一些屬性;與庫存有關的一些屬性;插入頭表時,要有一個接口獲取單據編號;因為插入行表時外鍵值需要用到頭表記錄的主鍵值,所以需要有個接口獲取頭表主鍵值,並有一個接口給行表實體的外鍵賦值;
   可能的變更: 1、將來可能增加審批功能,單據提交後審判通過才改變庫存;2、增加新的單據類型;3、將來增加訂單管理,那麼庫存操作除了出入庫、還會增加在途轉入庫存、庫存轉出在途等功能。
  

2、設計
   方案1、抽象類+子類,只關注操作,不關注數據;
         單據處理類 BillProcess (抽象類):
         公有虛方法 Save()/Submit()/Delete()
         私有虛方法 Log()/ChangeStock()
   擴展:增加審批功能,只需在基類增加新的虛方法Audit,子類實現新的虛方法; 增加單據類型時,只需實現新的單據,增加在途功能,只需修改 ChangeStock;
   評價:此方案雖然很容易擴展,除了需要對ChangeStock作修改外,基本符合開閉原則;但過於抽象,子類需要實現全部操作,基類僅僅起到規范方法名稱的作用;此方案的復用度太低;

   方案2、抽象類實現部分模板方法,所有方法都沒有參數,抽象類沒有任何字段,全部給子類實現;
         單據處理類 BillProcess (抽象類):
         公有虛方法 Save(): 調用IsNew()判斷是新增還是更新,如果是新增,設置單據編號SetBillNumber,插入頭表InsertHeader,設置行表外鍵SetBillLineHeaderID;若是更新,則更新頭表UpdateHeader,刪除行表DeleteLines(),設置行表外鍵SetBillLineHeaderID,插入行表InsertLines(); 調用 Log();
         公有虛方法 Submit(): 調用 Save(),調用 ChangeStock(); 調用 Log();
         公有虛方法 Delete(): 調用 DeleteHeader(),調用 DeleteLines(); 調用 Log();
        
         保護虛方法 IsNew,判斷是新增單據還是更新單據;
         保護虛方法 SetBillNumber

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved