面向對象的思想及其設計原則

面向對象

  • 面向過程:有一套設計嚴格的操作順序,有一個類似中央控制器的角色來進行統一調度

  • 面向對象:沒有明確的中央控制的角色,也不需要指定嚴格的操作順序,而是設計了很多對象,並且指定了這些對象需要完成的任務,以及這些對象如何對外界的刺激做出反應。

面向對象思想的適用範圍

  • 面向過程的方法主要是按邏輯流程,流水式地寫代碼。每次需求的變更,可能都要對邏輯流程的多個步驟進行修改,這樣的代價在軟件系統中幾乎是不可接受的,因爲每次修改都需要對全系統改動一次,不但工作量會大大增加,同時風險也在大大增加

  • 而面向對象正是爲了解決面向過程的這個缺點誕生的。面向對象的方法可以將變化帶來的影響控制在有限的範圍內,避免產生全流程或大範圍的影響,從而降低風險。面向對象思想的核心就是“可擴展性”,因此,經常變化的地方就是面向對象應用的地方。

    • 對於軟件系統來說,常見的可變的主要集中在客戶需求的部分,而不變的一般屬於計算機系統的基礎。

    • 操作系統、數據庫、協議(TCP、3GPP等)這些地方並不合適面向對象大展身手,因爲這些軟件基礎一般都比較穩定(相對穩定,並不是不變)。

    • 對於企業應用、互聯網、遊戲等應用,需求經常變更,功能不斷擴展,這正是面向對象大展身手的地方

面向對象理論

  • 類:具有相似點的事物就是同一類

    • 設計方法基本原則:方法單一化原則。即“一個方法只做一件事”

    • 設計屬性基本原則:屬性最小化原則。即“屬性不可拆分”

    • 屬性:類具有的特性

    • 方法:類具有的功能

  • 對象:一個具體的類

  • 接口:一組相關的交互功能點定義的集合

    • 用處:你不知道一個對象所屬的具體“類”,只知道這些對象都具備某種功能

  • 抽象類:基於類而抽象出來的,只能用於繼承,而不能用於實例化

    • 抽象類與接口的區別:抽象類本質還是類,強調一組事物的相似性,包括屬性和方法的相似性;接口只強調方法的相似性,並且僅僅體現在方法聲明上的相似性,而沒有方法定義實現上的相似性

  • 抽象:“抽取比較像的地方出來”。抽象的主要目的是劃分類別;隔離關注點,降低複雜度

  • 面向對象三大核心特徵:

    • 封裝:保護隱私、隔離複雜度

    • 繼承:抽象和繼承是前後銜接的關係,先有抽象,通過抽象得出類,後通過繼承來表達抽象結果

    • 多態:使用指向父類的指針或引用,能夠調用子類的對象。當增加新的子類時,調用者的代碼無須變動就能適用新的子類

面向對象分析和設計流程

需求模型

通過和客戶溝通,結合行業經驗和知識,明確客戶的需求

  • 需求:對客戶來說有價值的事情

  • 功能:系統爲了實現客戶價值而提供的能力

  • 需求分析要時刻抓住“客戶的問題和價值”這個指導思想:“挖掘客戶的問題,實現客戶價值”

需求分析方法:

  • 518:

    • 5W:When、Where、Who、What(客戶想要的到的輸出)、Why(客戶提出需求的驅動力:遇到的問題、困難、阻礙等)。最關鍵的是why,只有解決了客戶的問題,客戶纔會真正滿意

    • 1H:How(用例方法,描述整個流程如何運行)

    • 8C:8個Constraint。包括性能(Performance)、成本(Cost)、時間(Time)、可靠性(Reliability)、安全性(Security)、合規性(Compliance)、技術性(Technology)、兼容性(Compatibility)

  • 用例方法:描述需求的流程

    • 【用例名稱】

    • 【場景】:5W中的3個W:Who、Where、When

    • 【用例描述】:5W中的What和How,即用戶應該怎樣做,以及每個步驟步中的輸出

    • 【用例價值】:5W中的Why

    • 【約束與限制】:8C

  • 需求用例分析方法:用例方法三段法(NEA方法):

    • 其他了解客戶需求的方法:調查問卷、頭腦風暴、數據分析、數據挖掘、競爭對手分析等

    • 正常處理(Normal):通過和客戶溝通,分析需求的正常流程

    • 異常處理(Exception):在正常處理流程的步驟上,分析每一步的各種異常情況和對應的處理

    • 替代處理(Alternative):在正常處理流程的步驟上,分析每一步是否有其他替代方法,以及替代方法如何做

  • 提取功能:將用例中需要系統完成的事情(動詞)提取出來,就成爲了系統的功能

  • 將不同用例中的相同功能合併,得到功能描述表

  • 畫出系統順序流程圖

領域模型

基於需求模型,提煉出領域相關的概念

  • 發掘重要的業務領域概念;建立業務領域概念之間的關係

  • 從需求用例中找名詞、加屬性、連關係

  • 更多領域建模方法可參考:問題空間領域模型基本抽象方法

設計模型

以領域模型爲基礎,綜合面向對象的各種設計技巧,完成類的設計

  • 靜態模型:類模型。主要關注系統的“靜態”結構,描述系統包含的類,以及類的名稱、職責、屬性、方法,類與類之間的關係

    • 第一步:領域類映射

      • 軟件類的屬性、類關係:從領域類(只有屬性、類關係,沒有方法)映射;

      • 軟件類的方法:從需求用例中提煉出動詞,分配給已經有了屬性的軟件類

      • 軟件類與領域模型類相比,部分領域類被剔除,留下來的領域類映射成軟件類後,又增加了方法

    • 第二步:應用設計原則和設計模式(保證“可擴展性”)

      • 設計之道:

        • 設計模式:找到變化,封裝變化

          • 設計模式一句話總結

          • 先找到可能變化的地方,再來看具體使用哪個模式可以封裝這種變化

          • 找到變化:解決了“在哪裏”使用設計模型的問題,即回答了“where”的問題

            • 如果你不知道什麼會變化,就抱着懷疑一切的想法,一切都可能是變化的,找到“有限時間內可能發生的變化”

          • 封裝變化:解決了“爲什麼”使用設計模型的問題,即回答了“why”的問題

            • “封裝變化”意味着將變化的影響範圍控制到最小,將風險降到最低

            • “封裝變化”將變化封裝起來,使其只在有限的範圍內有影響

        • 設計原則:

          • 基於接口編程,而不是基於實現編程

          • 優先使用對象組合而不是類繼承

          • 開閉原則(OCP,Open-Closed Principle)總的指導思想,如果能符合LSP/ISP/DIP原則,一般就能符合OCP原則了

            • 模塊應儘量在不修改原代碼(閉)的情況下進行擴展(開)。在程序需要進行拓展的時候,不用去修改原有的代碼,實現一個熱插拔的效果。

            • 對使用者修改關閉,對提供者擴展開放。即:提供者增加新的功能,但使用者不需要修改代碼。

            • 系統和系統、子系統和子系統、模塊和模塊之間都可以應用開閉原則:通過接口交互

              • 類和類之間——使用interface進行交互

              • 模塊和模塊、系統和系統之間——使用規定好的協議交互,比如HTTP、SOAP等

          • 單一職責原則(SRP,Single Responsibility Principe)指導類的設計

            • 每個類只負責一組相關的事情

          • 里氏代換原則(LSP,Liskov Substitution Principe)指導類繼承的設計

            • 如果調用的是父類的話,那麼換成子類也完全可以運行。 派生類能夠在基類的基礎上增加新的行爲。只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用。

            • 實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。

          • 接口隔離原則(ISP,Interface Segregation Principle)指導接口的設計

            • 接口的功能要內聚,每一個接口應該是一種角色,不幹不該乾的事,該乾的事都要幹。

            • 調用接口的類可以根據自己的需要精確使用某個接口,而不是調用一個大而全的接口。降低類之間的耦合度。

          • 依賴反轉原則(DIP,Dependency Inversion Principle):指導如何抽象

            • 1、高層次的模塊不應該依賴於低層次的模塊,他們都應該依賴於抽象。

            • 2、抽象不應該依賴於具體實現,具體實現應該依賴於抽象。要求面向抽象/接口進行編程,不要對實現進行編程,這樣就降低了客戶與實現模塊間的耦合。

            • 通過抽象/接口交互;依賴抽象/接口,而不依賴具體實現。

          • 合成複用原則

            • 要儘量使用組合/ 聚合,儘量不要使用繼承。只有“Is - A” 關係才符合繼承關係,“Has- A” 關係應當使用聚合來描述。

          • 最少知識原則

            • 一個對象應對其它對象有儘可能少的瞭解。即一個實體應當儘量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。

          • 高內聚、低耦合

            • 內聚:當模塊(函數、類、包、子系統)的元素全部都專注於模塊的職責的時候,即使元素間的結合不是很緊密,也是符合內聚性的要求的。(這也是CRUD設計符合內聚性的原因)

          • 避免過度設計

      • 設計原則主要用於指導“類的定義”的設計(類的靜態設計原則)

      • 設計模型主要用於指導“類的行爲”的設計(類的動態設計原則)

      • 一般情況下,“先設計原則,後設計模型

    • 第三步:拆分輔助類

      • 拆分輔助類的主要目的是爲了使我們的類在編碼的時候能夠滿足一些框架或規範要求。比如常見的MVC模型,將一個業務拆分成Control、Model、View三個元素;在J2EE模式中,將對象分爲PO、BO、VO、DTO等衆多對象。

      • 拆分輔助類僅僅是爲了滿足框架或者規範的要求,僅僅在編碼的時候拆分即可,所以一般不需要將拆分的輔助類體現在類模型中。

      • 做法:將設計出來的類,按照規範要求,一一對應拆分。

      • 例子:POS機使用的場景裏有一個“購物卡”類,假如框架要求提供DAO對象,負責數據庫的相關操作,則“購物卡”類就應該拆分爲兩個:“購物卡”和“購物卡DAO”,其中“購物卡”用於負責提供支付功能給“交易”類調用;“購物卡DAO”用於負責從數據庫讀取購物卡信息,修改數據庫中的購物卡餘額等操作

  • 動態模型

    • 表達方式:主要是UML建模裏的工具:狀態模型、活動模型、序列模型、協作模型的等

    • 動態模型可以將複雜的業務用模型表示出來,其根本作用是便於我們去思考和理解實現過程,如果業務比較簡單,就很容易理解,就沒有必要設計動態模型了

    • 關注系統的“動態”行爲,描述類本身的一些動作或狀態變化,以及類之間如何配合以完成最終的業務功能。

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