面向對象之類的設計_代碼大全筆記(二)

類的基礎是抽象數據類型。抽象數據類型(ADT)是數據和對這些數據操作的集合。此“數據”爲泛指,可以是窗體,文件,鏈表,汽車,飛機,人等。

類還支持繼承和多態,因此可以認爲,抽象數據類型 + 繼承 + 多態 = 類

任何東西首先展示給人的都是外表,類需要一個良好的接口。(這裏的接口主要是指類提供的public函數的集合)

1.合理的抽象

類的接口爲隱藏具體實現而提供一種抽象,此接口應該提供一組明顯相關的操作。--情非得已別讓狗拿耗子

1.一致的抽象層

類設計時,把類看成是實現ADT的機制,每個類只實現一個ADT,若某個類實現了多個ADT,則應把這個類重新組織爲多個明確的ADT。

如某個類中一半的子程序使用一部分數據,另一半的子程序使用另一部分的數據,此時可能已經把兩個類混在一起了,可以考慮分開

2.理解類所實現的抽象

一些類非常相似,需要仔細理解類的接口,以確定所需要的抽象是哪個。

3.相反操作

開-關;添加-刪除;激活-禁用等,設計類時,不要盲目創建相反操作,要認真考慮,是否需要。-做事情不要太順手

4.抽象性和內聚性

好的抽象通常也有很高的內聚性,如果發現某個類的內聚性很弱,不知道如何修改,可以嘗試看看這個類是否表現了一致的抽象。

2.良好的封裝

抽象是忽略實現細節來管理複雜度,而封裝是阻止看到細節。--非禮勿視

1.儘可能限制成員的可訪問性

如果暴露一個子程序不會破壞抽象的一致性,則這麼做是可行的,否則隱藏之會更好。

2.不要公開(public)數據成員

公開數據會破壞封裝性,限制對抽象的控制能力。

3.避免把私有的實現細節放入類的接口中

可參考一中的隱藏抽象的實現細節一節的內容)把private段的內容放到類的頭文件中還是暴露了部分的實現細節,可以把類的接口和類的實現隔離開來,在類的接口文件中聲明一個指向類實現的指針。

4.避免使用友元

一般情況下友元會破壞封裝性,有些場合如設計模式中,使用友元是爲了管理複雜度。

5.讓閱讀代碼比編寫代碼更方便

這個說起來容易做起來也容易,難的是一般程序員不屑於做。-這說到心坎上了

6.留意過於緊密的耦合關係(兩個類之間關聯)

以下是一些指導建議

  • 儘可能限制類和成員的可訪問性
  • 避免友元類
  • 將基類數據聲明爲private而不是protected,以降低派生類和基類的耦合
  • 避免在類中暴露數據成員

3.類的設計和內部實現

包含(有一個的關係)纔是面向對象編程的主力技術。-聚合優先於繼承

1.萬不得已時通過private繼承來實現“有一個”的關係

某些情況下根本無法包含一個對象時,可以通過private繼承來實現。-private繼承實際是實現繼承,相當於將基類的public和protected成員以private聲明於子類

2.警惕有太多數據成員的類

研究表明,人們能記住的離散項目的個數是7±2。如果一個類有超過7個數據成員,可以考慮是否有必要分解爲更小的類。如果數據成員是整形型者字符串這類簡單數據類型,可以按7±2上限考慮,若是複雜對象,則按7±2下限考慮。-這個是否有點絕對化了,看到好多類都是超過這個數的,應該要視情況而言吧

 

當決定使用繼承(是一個的關係)時,考慮如下

  • 對於每個成員函數,應該對派生類可見嗎?應該有默認的實現嗎?此默認實現可以被覆蓋(override)嗎?
  • 對於每個數據成員,應該對派生類可見嗎?

1.public繼承實現“是一個......”的關係

如果派生類不準備完全遵守基類定義的同一個接口契約,就不應該用繼承。

考慮子類是否需要進行向上類型轉換,如果不需要,那麼繼承就不是正確的實現技術。-這個很關鍵,不需要多態時應考慮聚合

2.遵循Liskov替換原則

3.派生類的成員函數不要與基類中不可覆蓋的成員函數重名

如果一個函數在基類中是私有的,派生類就不要創建一個同名的成員函數。

4.公用的接口,數據放到繼承樹中儘可能高的位置

多高算高?當把子程序移到更高層次會破壞抽象性,就該停手。

5.派生類覆蓋某個子程序,其中沒做任何操作,這種情況需要注意

6.避免讓繼承體系過深

7.儘量使用多態,避免大量的類型檢查

8.讓所有數據都是private,而非protected

當決定使用多重繼承之前,應該仔細考慮其他解決方案。

何時使用繼承,何時使用包含

    • 多個類共享數據而非行爲,應該創建這些類可以包含的共用對象
    • 多個類共享行爲而非數據,應該從共同的基類繼承,在基類定義共用子程序
    • 多個類同時共享數據和行爲,應該從基類繼承,並在基類中定義共用的數據和行爲
    • 當需要用基類控制接口時,使用繼承;當想自己控制接口時,使用包含。

成員函數和數據成員

  • 讓類中子程序儘可能少
  • 禁止隱式地產生成員函數和運算符(類似將賦值運算符聲明爲private的方式
  • 減少類所調用的不同子程序的數量(扇入扇出概念
  • 對其他類的子程序的間接調用儘可能少

儘量減小類與類之前相互合作的範圍

儘量讓下面的數字最小

  • 所實例化的對象種類
  • 在被實例化對象上直接調用的不同子程序數量
  • 調用由其他對象返回的對象的子程序數量

4.創建類的原因

  • 爲現實世界中的對象建模
  • 爲抽象對象建模(經典的shape不是真實存在的)
  • 降低複雜度(信息隱藏,無需考慮他們了)
  • 隔離複雜度(隔離複雜算法,大型數據等)
  • 隱藏實現細節
  • 限制變動的影響範圍
  • 隱藏全局數據
  • 讓參數傳遞更順暢
  • 建立中心控制點
  • 代碼更易於重用
  • 爲程序族做計劃
  • 把相關操作包裝到一起
  • 實現某種特定的重構

5.應該避免的類

  • 避免創建萬能類
  • 消除無關緊要的類
  • 避免動詞命名的類

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章