面向對象七大設計原則的綜合闡述

来源:http://www.cnblogs.com/bdpsc/archive/2016/03/03/5237606.html
-Advertisement-
Play Games

面向對象原則綜述 七大原則總脈絡圖: 註:1,2,3,4,5顯示的重要等級 常用的面向對象設計原則包括7個,這些原則並不是孤立存在的,它們相互依賴,相互補充。 下麵就是面向對象七個原則的一一解析 一、開閉原則 1. 開閉原則定義 :一個軟體實體應當對擴展開放,對修改關閉。也就是說在設計一個模塊的時候


面向對象原則綜述

七大原則總脈絡圖:

            

               註:1,2,3,4,5顯示的重要等級

 

          常用的面向對象設計原則包括7個,這些原則並不是孤立存在的,它們相互依賴,相互補充。

          

 

 

下麵就是面向對象七個原則的一一解析

一、開閉原則

 

1.          開閉原則定義 :一個軟體實體應當對擴展開放,對修改關閉。也就是說在設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展,即實現在不修改源代碼的情況下改變這個模塊的行為。

 

 

2.          開閉原則分析:

(1)開閉原則由Bertrand Meyer於1988年提出,它是面向對象設計中最重要的原則之一。

(2)在開閉原則的定義中,軟體實體可以指一個軟體模塊、一個由多個類組成的局部結構或一個獨立的類。

(3)抽象化是開閉原則的關鍵。

(4)開閉原則還可以通過一個更加具體的“對可變性封裝原則”來描述,對可變性封裝原則(Principle of Encapsulation of Variation,EVP)要求找到系統的可變因素並將其封裝起來。

 

 

3.          開閉原則實例:

 

 某圖形界面系統提供了各種不同形狀的按鈕,客戶端代碼可針對這些按鈕進行編程,用戶可能會改變需求要求使用不同的按鈕,原始設計方案如圖所示:

 

 

                                

 

 

                                                                                     圖(1)

  現對該系統進行重構,使之滿足開閉原則的要求。

 

 

                                                                                                                             圖(2)

 

 

對比分析

圖(1):客戶端的一個方法直接調用加法類,但是我想添加一個減法類,你就會發現添加減法類就得改變加法類中代碼(用switch語句實現),這就違背了“開閉原則”,於是我們就應該重新重構。

圖(2)在這個圖中我們添加了一個運算類的父類,這樣我們再添加減法類的時候就不用修改客戶端類。

 

 

開閉原則總結:面對需求,對程式的改動是通過增加新代碼進行的,而不是改變原來的代碼。

 

二、依賴倒轉原則

 

 1. 依賴倒轉原則實例

        某系統提供一個數據轉換模塊,可以將來自不同數據源的數據轉換成多種格式,如可以轉換來自資料庫的數據(DatabaseSource)、也可以轉換來自文本文件的數據(TextSource),轉換後的格式可以是XML文件(XMLTransformer)、也可以是XLS文件(XLSTransformer   

 

圖(一)

 

圖(二)

圖(一)和圖(二)分析:

  圖(一)為什麼要到圖(二)哪?因為該系統可能需要增加新的數據源或者新的文件格式,每增加一個新的類型的數據源或者新的類型的文件格式,客戶類MainClass都需要修改源代碼,以便使用新的類,但違背了開閉原則。現使用依賴倒轉原則對其進行重構。

總結:高層模塊不應該依賴底層模塊,兩個都應該依賴與抽象;抽象不應該依賴於細節,細節應該依賴於抽象。

 

三、 里氏代換原則

 

1.      實例

     某系統需要實現對重要數據(如用戶密碼)的加密處理,在數據操作類(DataOperator)中需要調用加密類中定義的加密演算法,系統提供了兩個不同的加密類,CipherA和CipherB,它們實現不同的加密方法,在DataOperator中可以選擇其中的一個實現加密操作。如圖所示:

 

圖(一)

圖(二)

圖(一)和圖(二)分析:

圖(一)為什到圖(二)哪?因為如果需要更換一個加密演算法類或者增加並使用一個新的加密演算法類,如將CipherA改為CipherB,則需要修改客戶類Client和數據操作類DataOperator的源代碼,違背了開閉原則。現使用里氏代換原則對其進行重構,使得系統可以靈活擴展,符合開閉原則。

總結:子類型必須能夠替換掉它們的父類型。

 

四、單一職責原則

1.  定義

      i.  一個對象應該只包含單一的職責,並且該職責被完整地封裝在一個類中。

      ii. 就一個類而言,應該僅有一個引起它變化的原因。 

2. 分析

             i.  一個類(或者大到模塊,小到方法)承擔的職責越多,它被覆用的可能性越小,而且如果一個類承擔的職責過多,就相當於將這些職責耦合在一起,當其中一個職責變化時,可能會影響其他職責的運作。

             ii.類的職責主要包括兩個方面:數據職責和行為職責,數據職責通過其屬性來體現,而行為職責通過其方法來體現。

             iii.單一職責原則是實現高內聚、低耦合的指導方針,在很多代碼重構手法中都能找到它的存在,它是最簡單但又最難運用的原則,需要設計人員發現類的不同職責並將其分離,而發現類的多重職責需要設計人員具有較強的分析設計能力和相關重構經驗。 

3. 實例

         i. 某基於Java的C/S系統的“登錄功能”通過如下登錄類(Login)實現:

 

 

 

圖(一)

 

 

 

圖(二)

 

圖一和圖二有什麼區別哪?

圖(一)功能太過於集成,嚴重違反類的單一原則。

總結:就一個類而言,應該僅有一個引起它變化的原因。

五、介面隔離原則

1. 定義

        i.  客戶端不應該依賴那些它不需要的介面。

        ii.  一旦一個介面太大,則需要將它分割成一些更細小的介面,使用該介面的客戶端僅需知道與之相關的方法即可。 

2.分析

         i.  介面隔離原則是指使用多個專門的介面,而不使用單一的總介面。每一個介面應該承擔一種相對獨立的角色,不多不少,不幹不該乾的事,該乾的事都要乾。

         ii. 使用介面隔離原則拆分介面時,首先必須滿足單一職責原則,將一組相關的操作定義在一個介面中,且在滿足高內聚的前提下,介面中的方法越少越好。

        iii.  可以在進行系統設計時採用定製服務的方式,即為不同的客戶端提供寬窄不同的介面,只提供用戶需要的行為,而隱藏用戶不需要的行為

3.實例

         i. 下圖展示了一個擁有多個客戶類的系統,在系統中定義了一個巨大的介面(胖介面)AbstractService來服務所有的客戶類。如圖所示:

圖(一)

圖(二)

圖(一)和圖(二)分析:

圖(一)為什麼到圖(二)哪?因為這樣做既滿足了介面隔離原則,又滿足了單一原則,何樂而不為呢,但是也帶來了很多的不便,類增多了。

總結:類應該完全依賴相應的專門的介面

六、合成復用原則

1.定義

         i. 儘量使用對象組合,而不是繼承來達到復用的目的。

2.分析

         i.  合成復用原則就是指在一個新的對象里通過關聯關係(包括組合關係和聚合關係)來使用一些已有的對象,使之成為新對象的一部分;新對象通過委派調用已有對象的方法達到復用其已有功能的目的。簡言之:要儘量使用組合/聚合關係,少用繼承。

         ii. 在面向對象設計中,可以通過兩種基本方法在不同的環境中復用已有的設計和實現,即通過組合/聚合關係或通過繼承。

a)  繼承復用:實現簡單,易於擴展。破壞系統的封裝性;從基類繼承而來的實現是靜態的,不可能在運行時發生改變,沒有足夠的靈活性;只能在有限的環境中使用。(“白箱”復用 )

b) 組合/聚合復用:耦合度相對較低,選擇性地調用成員對象的操作;可以在運行時動態進行。(“黑箱”復用 )                                                                       

        iii. 組合/聚合可以使系統更加靈活,類與類之間的耦合度降低,一個類的變化對其他類造成的影響相對較少,因此一般首選使用組合/聚合來實現復用;其次才考慮繼承,在使用繼承時,需要嚴格遵循里氏代換原則,有效使用繼承會有助於對問題的理解,降低複雜度,而濫用繼承反而會增加系統構建和維護的難度以及系統的複雜度,因此需要慎重使用繼承復用。

3. 實例

     i. 某教學管理系統部分資料庫訪問類設計如圖所示:

圖(一)

圖(二)

圖(一)和圖(二)分析:

圖(一)為什麼到圖(二)哪?因為如果需要更換資料庫連接方式,如原來採用JDBC連接資料庫,現在採用資料庫連接池連接,則需要修改DBUtil類源代碼。如果StudentDAO採用JDBC連接,但是TeacherDAO採用連接池連接,則需要增加一個新的DBUtil類,並修改StudentDAOTeacherDAO的源代碼,使之繼承新的資料庫連接類,這將違背開閉原則,系統擴展性較差。

總結:類中應用,儘量使用對象組合而不是用繼承來達到復用的目的。

七、迪米特法則

               

1. 定義

    i. 每一個軟體單位對其他的單位都只有最少的知識,而且局限於那些與本單位密切相關的軟體單位。

2. 分析

    i.迪米特法則就是指一個軟體實體應當儘可能少的與其他實體發生相互作用。這樣,當一個模塊修改時,就會儘量少的影響其他的模塊,擴展會相對容易,這是對軟體實體之間通信的限制,它要求限制軟體實體之間通信的寬度和深度。

    ii. 狹義的迪米特法則:可以降低類之間的耦合,但是會在系統中增加大量的小方法並散落在系統的各個角落,它可以使一個系統的局部設計簡化,因為每一個局部都不會和遠距離的對象有直接的關聯,但是也會造成系統的不同模塊之間的通信效率降低,使得系統的不同模塊之間不容易協調。

    iii. 廣義的迪米特法則:指對對象之間的信息流量、流向以及信息的影響的控制,主要是對信息隱藏的控制。信息的隱藏可以使各個子系統之間脫耦,從而允許它們獨立地被開發、優化、使用和修改,同時可以促進軟體的復用,由於每一個模塊都不依賴於其他模塊而存在,因此每一個模塊都可以獨立地在其他的地方使用。一個系統的規模越大,信息的隱藏就越重要,而信息隱藏的重要性也就越明顯。

 

     iv. 迪米特法則的主要用途在於控制信息的過載。

 

1.在類的劃分上,應當儘量創建松耦合的類,類之間的耦合度越低,就越有利於復用,一個處在松耦合中的類一旦被修改,不會對關聯的類造成太大波及

2.在類的結構設計上,每一個類都應當儘量降低其成員變數和成員函數的訪問許可權

3.在類的設計上,只要有可能,一個類型應當設計成不變類 

4.在對其他類的引用上,一個對象對其他對象的引用應當降到最低。 

 

3. 實例 

      i.某系統界面類(如Form1、Form2等類)與數據訪問類(如DAO1、DAO2等類)之間的調用關係較為複雜。如圖所示:

 

圖(一)

圖(二)

圖(一)和圖(二)分析:

圖(一)為什麼到圖(二)哪?因為這樣就可以降低類的耦合性,是類中功能更加單一,相當於外觀模式。

總結:一個軟體實體應當儘可能少的與其他實體發生相互作用


這就是程式員必備的七大面向對象設計原則,很喜歡這樣的分享,希望你們參與進來,走近博客園、知識將源源不斷、、

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • public class HttpsTest { @SuppressWarnings("deprecation") public static void main(String[] args) { try { SSLContext context = SSLContext.getInstance("
  • php中讀取文件可以使用fopen和file_get_contents這兩個函數,二者之間沒有本質區別,只是前者讀取文件的php代碼相比後者要複雜一點。本文章通過實例向大家講解fopen和file_get_contents讀取文件的實現代碼。需要的碼農可以參考一下。 fopen讀取文件的代碼如下:
  • Java 異常處理方法 Java catch多個異常處理 Java Finally實例 Java 如何使用 catch 處理異常 Java 多線程異常處理實例 Java 如何獲取異常的堆棧信息 Java 重載方法異常處理 Java 鏈試異常實例 Java 如何自定義異常處理
  • 學習maven項目時 搭建個ssm項目 算是給自己留個備份吧 環境說明: MyEclipse10 Maven 3.2.3 框架: struts2 2.3.24.1 spring3 3.0.5.RELEASE mybatis 3.2.2 資料庫: mysql 5.7 <project xmlns="h
  • 所謂“單例”: 單例模式是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例而且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。如果希望在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。 C#中的例子: 轉:htt
  • 1 package com.shejimoshi.behavioral.Iterator; 2 3 4 /** 5 * 功能:我們的迭代器介面 6 * 時間:2016年3月4日上午9:17:36 7 * 作者:cutter_point 8 */ 9 public interface MyIterat
  • 1、概念:裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象,又叫做包裝模式。 2、在java的IO流這個章節中,我們會發現有底層流,比如說位元組和字元流,有緩衝流等等: FileOutputStream:基本的文件輸出流 B
  • 引言 用過ASP.NET WebApi2.0, 上次去面試被問到什麼是Restful ,一時間竟不知道從何說起,所以搜集資料,做個備註,有時間好多來看看加深理解。 什麼是Restful 一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和伺服器交互類的軟體。基於
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...