OOD 面向對象設計規范(總結)





類的多 (Polymorphism) 面向對象程序設計的最核心特征

    接口的多種不同的實現方式為多態。為類在面向程序設計中的一個重要特性。如果一種語言只是支持類和非支持多態性的話只能說此語言是基於對象的而非面向對象的。

                可以理解為允許將父對象設置成一個或者更多的它的子對象的相等技術,賦值之后父對象可以根據當前賦值給它的子對象的特征以不同的方式運作。

    目的 把不同的子類對象都看作父類對象,這樣可以屏蔽不同子類對象之間的差異寫出通用代碼從而適應需求的不斷變化。簡單的說就是父類的行為像似子類。

                也就是說可以使一個對象有着多重的特征,可以在特定的情況下來表現出不同的狀態從而對應不同的屬性和方法。

                發送消息(調用類的方法)給某個對象讓該對象自己決定響應何種行為(子類中的方法)。

    實現方法 針對基類寫出程序同時可以適應這個類的家族,將子類對象地址賦值給基類,通過基類來訪問其子類的對象。編譯器通過動態綁定的手段來會找出合適的對象來執行操作。

    運行時多態 過引用變量發出的方法調用在編程的時候並不確定,而是在程序運行期間才能確定。即一個引用變量到底會指向哪個類的實例對象以及引用變量發出的方法調用到底是在哪個類中

                 實現的方法必須由程序運行期間才能決定。所以此多態是一種運行期的行為而非編譯期的行為。



抽象類 abstract):

     一個類中沒有包含足夠的信息來描繪一個具體的對象的話,這樣的類就是抽象類。

     分別 C++中的純虛擬函數類稱為抽象類。在JavaPHP中含有抽象方法的類稱為抽象類。此種類不能生成對象。同時抽象類由於是非完整的所以只能用作基類。

     目的 用來表征對問題領域進行分析,設計中的出的抽象概念,是一系列看上出不同但是本質上相同的具體概念的抽象。(例如形狀概念就是一個抽象概念)

     特征 1 無法實例化。

                  2 從抽象類派生的非抽象類必須實現繼承的所有抽象方法和抽象訪問器。

                  3 可以包含抽象成員變量。

                  4 可以包含非抽象的成員方法。

                  5  義上偏重ISA(是一個什么東西)關系。



接口 Interface 

     邏輯抽象的一種方式,照比抽象類更加抽象的方式。接口屬於類所具有的一種規范,定義了實現接口的類所應該遵循的標准。

     目的 可以使類具有靈活性,可擴展性以及可插入性。同時保證實現同一接口的類遵守同一協議(抽象方法的實現)。

     特征 接口只有方法的特征而沒有方法的實現,從而接口的方法可以在不同的地方被不同的類來實現從而這些實現可以具有不同的功能。同抽象類一樣,也不可以直接對接口進行實例化。

                  Java中可以理解為只有抽象方法聲明的抽象類。

                  接口中的方法都默認使public abstract類型的。

                  接口偏重於CANDO方面(實現接口的類需要實現接口的抽象方法從而達到類對接口所定義功能的實現)。

                  可插入性 在一個類的等級結構中的任何一個類都可以實現接口,這個接口會影響到此類的所有子類但是不會影響到此類的父級類(超類)。此種方式可以使大規模軟件系統的靈活性,可擴展性和可插入性得到保證。



關於抽象和結構的一個個人理解分析

      門的類設計相關問題  

          1 門在設計中,基本的門包含開關兩個動作。所以定義開關這兩個方法的時候需要設計一個抽象類來包含開關兩個抽象定義(抽象類屬於ISA)。

          2 如果有些悶具有報警功能的話,這個時候並不是所有的門具有報警功能,外加報警使屬於門可以實現的一種動作(符合接口CANDO的定義),所以報警功能的定義應該放置到接口中。

             讓具有報警功能的門的類實現報警的接口,從而實現報警處理。



方法重載(Overloading Method):

    在一個類中頂一個多個同名的成員方法,但是每個同名方法具有不同的參數的類型或者參數個數。在調用重載方法的時候,編譯器可以根據參數的類型或者個數選擇適當的方法。

                 但重載與多態無關。

    目的 可以讓類以統一的方式處理不同類型數據的手段。

    要求規范 1 方法名一定要相同。

                        2 參數表必須不同(參數的類型和個數)

                        3 參數的返回類型,修飾符可相同也可不同。[非必須項目,由於編譯器是通過參數(非返回值)來判斷程序是在調用哪個方法]

                        4 載的方法要在同一個類中。



方法重寫(Overwriting Method

    方法重寫又稱為方法覆蓋。子類對父類成員方法的重新改寫覆蓋的手段。

    目的 子類想對父類的方法非原封不動的繼承而是想做一定的修改。

    要求規范 1 子類的方法名需要與父類的方法名同名,同返回類型以及同參數表。

                        2  子類的方法不能比父類中被覆蓋的方法有更嚴格的訪問權限。

                        3  如果子類需要使用父類的原有方法的時候,可使用super鍵字來引用父類的方法。


方法隱藏 Java): 

    場景 一個父類的引用指向子類的對象時候,這個時候要考慮到編譯器的運行機制RTTIrun-time type identification運行期類型檢查),這個時候對這個實例化的對象進行訪問的時候的情況。

    在子類中聲明和父類相同的靜態方法可以將父類的方法隱藏。

    目的 由於不能重寫父類的靜態方法,所以通過隱藏的手段來隱藏父類的靜態方法。但是此時便無法適用於多態的開發方式。

    特征 1 隱藏父類的靜態方法只是使父類和子類的靜態方法各自獨立開來。從而成為一種形式上的方法隱藏。

                 2 (由於RTTI機制)在使用多態的方式時,如果引用為父類引用而引用所指向的為子類的實例化對象的時候,這時如果調用子類的重名靜態變量的時候,反而會去調用父類的靜態方法。

                 3 (由於RTTI機制)在使用多態的方式時,如果引用為父類引用而引用所指向的為子類的實例化對象的時候,如果調用子類的的重名靜態變量和非靜態變量的時候,返而會去調用父類的靜態變量和非靜態變量。

                 4 (由於RTTI機制)在使用多態的方式時,如果引用為父類引用而引用所指向的為子類的實例化對象的時候,如果調用子類的的重名非靜態方法的時候,會去調用子類的非靜態方法。

    總結 在多態的情況下,父類引用而指向子類實例的時候,靜態變量和函數以及非靜態變量的信息均不會通過RTTI進行多態,而非靜態函數會通過RTTI實現多態。




虛函數 針對C++): 

    在基類中聲明virtual並且在一個或多個派生類中被重新定義的成員方法。主要目的是為了實現類的多態。

    在基類中需要實現多態的函數加上virtual的前綴之后,子類中出現同名同參數表的函數的時候,在運用多態的情況下,就會現實子類的方法覆蓋父類的方法。

   





作用 為面向對象編程定義了基本的規范,為面向對象編程的主要思想。

             2  軟件設計階段來從全局出發考慮來解決此階段的問題。(比如類和代碼的模塊化以及重用等)


總體總結 

             1 不要破壞繼承關系。(里氏替換原則)

             2 面向接口編程。(依賴倒置原則)

             3 設計接口的時候要精簡單一。

             4 降低耦合。

             5 對擴展開放對修改關閉。(開閉原則)

             6 實現的類要職責單一。(單一責任原則)



使用OOD的理由  

軟件處在時刻進化和變化中的,后期需求可能較前期來說有很大變化。

    針對此,軟件需要被設計成一款敏捷的軟件。(可以輕松應對變化可被擴展和復用) OOD是完成此目的的關鍵。


2


    判斷一款軟件是否應用了OOD的條件

    1  面向對象

    2  復用

    3  變化的情況下所需的代價極小

    4  無需修改代碼即可擴展


    SOLID 設計原則的基本): 

    S  --  單一責任原則

        一個類或者模塊應該只有一個改變的原因。也就是說不要存在多於一個導致類變更的原因。

         正方形的類包含計算面積和描繪兩個功能。應該將計算和描繪同時放到兩個類中,以防止其中一個功能改變時影響到另一個功能。

       產生職責擴展的時候 應該立刻重構代碼以防止代碼在未來的不確定性。(如果類的本身現在情況以及預期的的內容都會極度簡單的情況下可以暫時不遵循單一責任原則,否則就需要絕對遵守)

       優點   1 降低類的復雜度並且高可讀性且容易維護。 2變更的情況下風險低,顯著地降低對其他功能的影響。


    O -- 閉原則 (面向對象設計中最基礎的設計原則)

          :一個如軟件實體(類,模塊和函數),應該對擴展開放而對修改關閉。

          需要解決的問題場景 軟件生命周期內,因為變化,升級,維護等原因需要對軟件原有代碼進行修改的時候,可能會對舊代碼造成影響從而引發錯誤,從而導致不得不對整個功能重構和重新測試。

          解決方案 軟件的需求發生變化的時候,進行通過擴展實體(類,模塊和函數)來實現變化,而非通過修改已有代碼來實現變化。

                              主旨 用抽象構建框架,用實現來完成細節。

          理解 設計原則中最抽象的原則,並且對單一責任原則,里氏替換原則,依賴倒置原則,接口隔離原則的遵守程度越好則對開閉原則達到了較好的遵守。


    L  --  Liscov換原則(里氏替換原則)

         有一個功能P1是由類A來完成的,此時對P進行功能擴展從而成為功能P(包含功能P1與新功能P2)。新擴展而成的功能P是由類A的子類B來完成。則子類B在王城新功能P2的同時,可能會有

         導致功能P1發成故障。這是由於父類已經實現好的方法實際上是在設定一系列的規范和契約,雖然不強制要求所有的子類必須遵循這些契約但是如果子類對這些實現好的方法進行任意修改的話就會

         給整個繼承體系造成破壞。

         時需要的應對方案為類B對類A進行繼承的時候,完成新功能P2需要添加對應的方法外,盡量不要重寫父類A的方法以及重載父類A的方法。

         總體原則 子類可以擴展父類的功能,但不能改變父來原有的功能。

             1 子類可以實現父類的抽象方法但是不可以覆蓋父類的抽象方法。

             2 子類可以增加自己特有的方法。

             3  當子類的方法重載父類的方法時,方法的前置條件(參數)要比父類方法的輸入參數更加寬松。(????不理解)

             4  當子類的方法要實現父類的抽象方法時,方法的后置條件(返回值)要比父類的更加嚴格。 (返回值要比父類的返回值更加具體)


    I   --   接口隔離原

            場景 如果一個接口過於臃腫,會導致很類在實現其的時候同樣要實現用不到的方法。為了避免這個問題,所以需要將這個臃腫的接口進行拆分,讓類來實現對應需要的接口。

            解決后的優點  可以預防外來的變更和擴展來提高系統的靈活性和可維護性。

            建立單一的接口而非龐大臃腫的接口同時盡量細化接口。

            接口盡量要小,但是小的限度可能會造成接口數量過多從而導致設計復雜化。

                         2  為依賴接口的類定制對應的方法,接口只需要定義調用的類需要的方法。只有專注地為一個模塊定制方法才能建立最小的依賴關系。

                         3  提高內聚減少對外交互,使接口用最少的方法去完成最多的事情。


    D  --  賴倒置原則

           層模塊不應該依賴低層模塊,二者都應該依賴其抽象。抽象不應該依賴細節,而細節應該依賴於抽象。

           可解決的事例 A賴於類B,如果將類A為依賴類C,必須通過修改類A的代碼來完成。此場景中類A屬於處理復雜業務的高級模塊,類BC屬於處理基本的原子操作的底層模塊。

                        時如果修改類A話會給程序帶來風險。

           上事例需要的解決方案  

                        將類A修改為依賴接口I(關聯的對象),類B和類C各自實現接口I。類A過接口I和類B,類C進行聯系。這樣就會降低修改A風險。 

           基於的思想 對細節的多變性,抽象要穩定的多。以抽象為基礎搭建起來的架構要比細節為基礎的架構穩定的多。(抽象:抽象類或者接口,細節 具體的實現類)

                        使用抽象類或者接口的目的是制定好規范和契約而不去干涉任何具體的操作,實現類去完成具體的實現細節任務。

                        所以總的核心思想為面向接口編程。

           總體原則 A調用關聯類B和類C對象的時候,只需要讓這個對象是接口I類型的就可以。所需要完成的動作放在接口中先進行抽象定義。


     迪特米法 (又稱為最少知道原則 Law of Demeter): 

           一個對象應該對其他的對象保持最少的了解,極為類與類之間的關系應該保持為低耦合高內聚。

           目的 提高類的復用率以及減少類互相之間的影響,從而解決類之間的耦合問題。

           實現方式 對於被依賴的類來說,無論邏輯多么復雜都要盡量地將邏輯封裝在類的內部,對外除了提供public方法意外不泄漏任何信息。

           總體原則  

                              1 類與類之間不應該發生直接的相互左右。

                              2 一個類如果需要調用另一個類的某一個方法的話可以通過第三方的類(中介的類)轉發這個調用。






注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com