第 6 章:擴展性設計 6.1 擴展機制 考慮用不包含任何虛成員或受保護的成員的非密封類來為框架提供擴展性。這種方法所提供的擴展性廣受用戶歡迎,而且它的開銷也不高。 考慮將受保護的成員用於高級的定製方案。 要在對安全性、文檔及相容性進行分析時,把非密封類中受保護的成員當做公有成員那樣來對待。 考慮使 ...
第 6 章:擴展性設計
6.1 擴展機制
考慮用不包含任何虛成員或受保護的成員的非密封類來為框架提供擴展性。這種方法所提供的擴展性廣受用戶歡迎,而且它的開銷也不高。
考慮將受保護的成員用於高級的定製方案。
要在對安全性、文檔及相容性進行分析時,把非密封類中受保護的成員當做公有成員那樣來對待。
考慮使用回調函數來允許用戶向框架提供自定義的代碼供框架執行。
考慮使用事件來允許用戶對框架的行為進行定製,這樣就不需要用戶對面向對象設計有深入的瞭解。
要優先使用事件,而不是簡單的回調函數,其原因在於廣大開發人員更熟悉事件,而且事件與 VS 的語句自動完成特性結合得很好。
避免在對性能要求很高的 API 中使用回調函數。
要在定義用了回調函數的 API 時,使用新的 Func<...>、Action<...> 或 Expression<...> 類型,而不要使用自定義的委托。
要在用 Expression<...> 來代替 Func<...> 和 Action<...> 委托的時間進行測量,從而瞭解它可能對性能產生的影響。
要理解在調用委托時可以執行任何代碼,這可能會引起安全性、正確性及相容性的問題。
不要使用虛成員,除非有合適的理由,而且對設計、測試及維護虛成員的開銷有清楚地認識。
要優先使用受保護的虛成員,而不是公有虛成員。公有成員應該通過調用受保護的虛成員的方式來提供擴展性(如有必要)。
不要提供抽象,除非為該抽象開發出多個具體實現並通過用到該抽象的 API 對其進行過的實際測試。
要在設計抽象時謹慎地選擇抽象類或介面。
考慮為抽象的具體實現提供參考測試。這類測試應該能告訴用戶,他們是否正確地實現了契約。
6.2 基類
考慮將基類定義為抽象類,即使他們並不包含任何抽象成員。這能夠清楚地告訴用戶,設計這些類的目的完全是為了讓用戶使用它們來派生自己的子類。
考慮把基類與用於主要場景的類型分開,並放到單獨的命名空間中。根據定義,基類是為了高級的擴展場景而設計的,因為大多數用戶對它們並不感興趣。
避免在命名基類時使用“Base”尾碼 - 如果公共 API 會用這個類。
6.3 密封
不要把類密封起來,除非有恰當的理由。
不要在密封類中聲明受保護的成員或虛成員。
考慮在覆蓋成員時將其密封。