面向對象的六大原則

来源:http://www.cnblogs.com/jilodream/archive/2016/04/05/5353512.html
-Advertisement-
Play Games

現在編程的主流語言基本上都是面向對象的。如C#,C++,JAVA。我們在使用時,已經構造了一個個的類。但是往往由於我們在類內部或外部的設計上存在種種問題,導致儘管是面向對象的語言,卻是面向過程的邏輯,甚至維護起來異常困難。每次增加或修改功能都要改動很多的代碼,如履薄冰。而面向對象的六大原則主要的目的 ...


  現在編程的主流語言基本上都是面向對象的。如C#,C++,JAVA。我們在使用時,已經構造了一個個的類。但是往往由於我們在類內部或外部的設計上存在種種問題,導致儘管是面向對象的語言,卻是面向過程的邏輯,甚至維護起來異常困難。每次增加或修改功能都要改動很多的代碼,如履薄冰。而面向對象的六大原則主要的目的,就是我們如何設計類,更能很好的利用面向對象的特性。

1)單一職責原則

一個類永遠只有一個職責。

  一套軟體就像是一個團隊,每個類就是團隊中的一個成員。團隊如果想穩定的發展。這些類就要各司其職,分工明確。如果類之間的功能出現了混淆,那麼軟體的整體結構就會非常的混亂。就像管理學中的一句話,如果一個職責由每個員工負責,那麼這個職責就沒有員工在負責。 這個原則的概念非常簡單,也是非常基礎的。很多人儘管沒有學習過面向對象的思想,但是經常寫代碼之後也會不自覺的遵守這個原則。 Ps:在遵循單一職責原則的時候,常常會遇到職責擴散的問題。什麼是職責擴散呢?這裡簡單說下,在日誌生活中,我們在分類職責時,發現很多平常不受重視的職責,但是這些職責又不能忽視。於是就依次累加,最後分起類來會無窮無盡(有興趣的讀者可以參考下長尾定理)。為瞭解決這種問題,我們就需要有一些類,他的職責比較綜合(類似於“其它”)。類似於一個幫助類。但是這個類又不能太複雜了,否則我們就應該考慮怎麼把這個類分離開來。究竟這個類的複雜程度到了什麼時候情況下,我們就應該拆分呢?這個需要程式員根據軟體自身的複雜情況來判斷,沒有一個統一的標準。

2) 里氏替換原則

“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”

——“繼承必須確保超類所擁有的性質在子類中仍然成立“

   這個原則主要是為了體現面向對象的“繼承”特征來提出的。 它的主旨就是,能夠使用基類的地方,必然也能夠透明的使用其子類,並且保證不會出錯。為了保證這種透明的無差別的使用,子類在使用時不應該隨意的重寫父類已經定義好的非抽象的方法。因為這些非抽象方法,類似於某種職能或契約,當父類保持這種約定時,子類也應該遵循並保證該特性,而非修改該特性。 我們在寫代碼的時候,如果一個參數設定的是基類(或介面、抽象類),那麼我們傳送子類進去,一樣可以正常使用。因為基類相對於父類,只是一個更豐富,更具體,更詳細的表現形式。而不應該出現,傳入父類運行某種方法沒有問題,可是傳入子類運行時就報錯了。這在日常生活中也可以理解,汽車作為父類,他下麵有卡車、轎車。轎車下邊又有兩廂,三廂等不同的繼承。但是無論是哪種汽車(父類)的職能,對於他的子類(卡車或轎車)都應該具有相同的職能,而不是相反的職能。以至於子類的子類(本例中是兩廂轎車)也應該擁有汽車一致的功能。

  我們在寫代碼中,很容易出現覆寫了父類的方法後,父類的方法發生了改動,而未考慮到子類的方法也需要作出相應的改動,導致代碼出現錯誤。 通俗一點,可以理解為子類是遺傳自父類的。他在各種職能上也應該一脈相承自父類。而不應該隨意改變。  

 

  Ps 為什麼要叫里氏替換原則呢?這是因為最早提出這個理論的人姓里Liskov。這是電腦中少有的以姓氏命名的東西。

 3)最少知道原則

Only talk to your immediate friends。(已經第二次引用英文,是不是很厲害23333)

永遠只和你的朋友交流。

  我們在學習編程的初期,都會有人告訴我們要遵循“高內聚,低耦合”。而OO中也將“封裝”作為對象的基本特征之一。最少知道原則其實體現的就是“高內聚,低耦合”這句話。

(1)低耦合:一個類對於自己依賴的類,知道的越少越好。不要讓一個類依賴過多的類。否則這個類很容受外界的影響,並且因為這種影響要改變自身的代碼(自身要適應)。

(2)高內聚:將實現邏輯都封裝在類的內部,對public方法以外的信息,不輕易暴露給外界。這是由於public對外後,相當於是一種契約,一種許諾。你要再後邊的實現中,不斷的去相容這種public,以防止調用它的代碼不會報錯。 上面這樣說,可能有點抽象,這裡舉個例子。在很多人對另一方的要求,都有一條,社會關係不要複雜。為什麼會這樣呢?因為一個人如果他和外界的關係越複雜,他就越不穩定,不怕人找事,就怕事找人。或許他的本性是好的,但是周邊的龍魚混雜,三天兩頭的總會有事。避免這種問題的最好辦法,就是一開始就做一個安靜的美男子。  

 

4)介面隔離原則

一個類對於另外一個類的依賴應該建立在最小的介面上。

  一個介面定義的過於臃腫,則代表他的每一個實現類都要考慮所有的實現邏輯。如果一個類實現了某個介面,也就是說這個類承載了這個介面所有的功能,維護這些功能成為了自己的職責。這就無形中增加了一個類的負擔。

這裡有兩點需要說明一下:

(1)介面定義的小,但是要有限度。對介面細化可以增加靈活性,但是過度細化則會使設計複雜化。同時介面的使用率不高,提高了代碼的維護成本。這種極端的體現就是每個介面只含有一個方法,這顯然是不合適的。

(2)介面隔離原則和單一原則的區別

共同點:都是儘可能的縮小涉及的範圍。

不同點:單一原則主要是指封裝性。他針對的是一個類、一個方法,是從對象的角度考慮的。而介面隔離原則是指類之間的耦合應該保持的一個度。他針對的是類(對象)和類(對象)之間的關係。如果說單一原則指的是思想單純,那麼介面隔離指的就是社會關係簡單啦。

5)依賴置換原則

這個原則的名字比較唬人,我們先看看他的內容究竟是什麼。在設計模式中對該原則有兩句經典的描述:

(1)高層模塊不應該依賴底層模塊。兩者都應該依賴抽象。

(2)抽象不應該依賴細節,細節應該依賴抽象。

  這兩句話的含義是:高層模塊不應該依賴底層模塊。兩者應該通過抽象的東西進行關係鏈接(抽象的東西是指介面或者抽象類)。其次抽象類或者一個介面不應該依賴某個實現類。而這些實現類反而應該依賴於這個抽象類的設定。

通俗一點的說法就是,模塊之間不應該直接產生調用關係(這是舊有的調用關係),兩者應該通過面向介面(或者理解為面向設定的契約)進行編程。而這些契約和介面更不應該以來自底層模塊而設定。這些底層模塊反而應該遵守這些契約。因為契約(抽象類、介面)相對於哪些實現代碼,更不會改變,也就是更穩定。所以依賴置換原則又叫作面向介面編程或面向契約編程。本意就是調整原來的依賴關係,重行進行了設定。  

6)開閉原則

開閉原則是指:一個軟體、一套系統在開發完成後,當有增加或修改需求時,應該對拓展代碼打開,對修改原有代碼關閉。

  類一旦確定,就不應該再對其功能發生修改。這是面向對象設計中,最重要最核心的原則。方案發佈後,我們最擔心的是什麼?就是需求的變化,而需求一旦有變化,就要修改代碼。大部分的bug往往就是這時候引入的。因為修改代碼時,我們往往將重點放在,如何解決當前bug上,反而沒有註意因為這個修改,對原有設計的影響。

這條原則沒有具體的指導要求,是前邊五條原則的根本。

 

ps,這六個面向對象的原則,並不是是和否的問題,也不是遵守和不遵守的問題。而是遵守的多和遵守的少的問題。我在文中也多次強調,我們在設計時,應該註意把握一個度。誠然儘可能的遵守這些原則,會使代碼維護起來更容易。但是維護粒度過細,所需要的設計和開發成本成倍增加,這顯然是捨本逐末的。如圖,面向對象開發原則可以從以下這個坐標圖展示,不論是哪個維度,他的值都不應該過滿,甚至溢出,當然也不能很低,保持一個適當的度即可。

 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • PHP的語言規範: 1、php中的變數名區分大小寫,但是函數名,類名,方法名,不區分大小寫,但建議區分大小寫 2、php代碼必須書寫在(php標簽),開啟標記(<?php)中間不能空格 3、php代碼每一行以分號結束,最後一行可以省略分號。 4、如果一個Php文件是由純 php代碼組成,那麼php結... ...
  • i = 0def myFun(): global i i=i +1 return i myFun() accumulate( ) total = 0def accumulate(): global total total += 1 return total ...
  • oauth應該屬於security的一部分。關於oauth的的相關知識可以查看阮一峰的文章:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 一、目標 現在很多系統都支持第三方賬號密碼等登陸我們自己的系統,例如:我們經常會看到,一些系統使用微 ...
  • 最近遇到的問題小結: 1.django 工程內不要有與項目名稱相同的文件。會導致無法import settings.py文件。 2.django 的 csrf 問題,當發送post請求時,會要求同時發送csrf token,是為了防止跨站請求偽造。 具體使用方法見官方文檔。 http://docs. ...
  • 介紹 我發現了一個問題,今天與大家分享。我把整個過程描述一下。 問題 問題 公司有個框架是基於smarty寫的,我負責php的升級,維護人員把新環境布上來之後,測試人員找我提出經常報錯(錯誤:提示找不到文件的)。 我追蹤了一下代碼,原來是smarty的這個地方報的錯誤。 錯誤:這裡報出文件不存在。 ...
  • 開篇導讀 “養成良好的編程習慣”其實是相當綜合的一個命題,可以從多個角度、維度和層次進行論述和評判。如代碼的風格、效率和可讀性;模塊設計的靈活性、可擴展性和耦合度等等。要試圖把所有方面都闡述清楚必須花很多的精力,而且也不一定能闡述得全面。因此,本系列文章以軟體開發的基礎問題為切入點,闡述程式設計和代 ...
  • 初始化一個map 1 2 3 4 5 Map<String, String> map = new HashMap<String, String>(); map.put("1", "hell"); map.put("2", "hello"); map.put("3", "hel"); map.put( ...
  • 幹掉這道題的那一刻,我只想說:我終於**的AC了!!! 最終記憶體1344K,耗時10282ms,比起歸併樹、劃分樹以及其他各種黑科技,這個成績並不算光彩⊙﹏⊙ 但至少,從最初的無數次TLE到最終的AC,這過程見證了一個二分演算法的艱辛優化 先貼代碼: 1 const int bktSize=1024; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...