1. 程式人生 > >面向物件的五大基本原則

面向物件的五大基本原則

面向物件的5大基本設計原則:

單一職責原則(Single-Resposibility Principle)

    其核心思想為:一個類,最好只做一件事,只有一個引起它的變化。單一職責原則可以看做是低耦合、高內聚在面向物件原則上的引申,將職責定義為引起變化的原因,以提高內聚性來減少引起變化的原因。職責過多,可能引起它變化的原因就越多,這將導致職責依賴,相互之間就產生影響,從而大大損傷其內聚性和耦合度。通常意義下的單一職責,就是指只有一種單一功能,不要為類實現過多的功能點,以保證實體只有一個引起它變化的原因。
    專注,是一個人優良的品質;同樣的,單一也是一個類的優良設計。交雜不清的職責將使得程式碼看起來特別彆扭牽一髮而動全身,有失美感和必然導致醜陋的系統錯誤風險。



開放封閉原則(Open-Closed principle)

    其核心思想是:軟體實體應該是可擴充套件的,而不可修改的。也就是,對擴充套件開放,對修改封閉的。開放封閉原則主要體現在兩個方面1、對擴充套件開放,意味著有新的需求或變化時,可以對現有程式碼進行擴充套件,以適應新的情況。2、對修改封閉,意味著類一旦設計完成,就可以獨立完成其工作,而不要對其進行任何嘗試的修改。
    實現開開放封閉原則的核心思想就是對抽象程式設計,而不對具體程式設計,因為抽象相對穩定。讓類依賴於固定的抽象,所以修改就是封閉的;而通過面向物件的繼承和多型機制,又可以實現對抽象類的繼承,通過覆寫其方法來改變固有行為,實現新的拓展方法,所以就是開放的。

    “需求總是變化”沒有不變的軟體,所以就需要用封閉開放原則來封閉變化滿足需求,同時還能保持軟體內部的封裝體系穩定,不被需求的變化影響。

Liskov替換原則(Liskov-Substituion Principle)

    其核心思想是:子類必須能夠替換其基類。這一思想體現為對繼承機制的約束規範,只有子類能夠替換基類時,才能保證系統在執行期內識別子類,這是保證繼承複用的基礎。在父類和子類的具體行為中,必須嚴格把握繼承層次中的關係和特徵,將基類替換為子類,程式的行為不會發生任何變化。同時,這一約束反過來則是不成立的,子類可以替換基類,但是基類不一定能替換子類。
    Liskov替換原則,主要著眼於對抽象和多型建立在繼承的基礎上,因此只有遵循了Liskov替換原則,才能保證繼承複用是可靠地。實現的方法是面向介面程式設計:將公共部分抽象為基類介面或抽象類,通過Extract Abstract Class,在子類中通過覆寫父類的方法實現新的方式支援同樣的職責。

    Liskov替換原則是關於繼承機制的設計原則,違反了Liskov替換原則就必然導致違反開放封閉原則。
    Liskov替換原則能夠保證系統具有良好的拓展性,同時實現基於多型的抽象機制,能夠減少程式碼冗餘,避免執行期的型別判別。

依賴倒置原則(Dependecy-Inversion Principle)

    其核心思想是:依賴於抽象。具體而言就是高層模組不依賴於底層模組,二者都同依賴於抽象;抽象不依賴於具體,具體依賴於抽象。
    我們知道,依賴一定會存在於類與類、模組與模組之間。當兩個模組之間存在緊密的耦合關係時,最好的方法就是分離介面和實現:在依賴之間定義一個抽象的介面使得高層模組呼叫介面,而底層模組實現介面的定義,以此來有效控制耦合關係,達到依賴於抽象的設計目標。
    抽象的穩定性決定了系統的穩定性,因為抽象是不變的,依賴於抽象是面向物件設計的精髓,也是依賴倒置原則的核心。
    依賴於抽象是一個通用的原則,而某些時候依賴於細節則是在所難免的,必須權衡在抽象和具體之間的取捨,方法不是一層不變的。依賴於抽象,就是對介面程式設計,不要對實現程式設計。

介面隔離原則(Interface-Segregation Principle)

    其核心思想是:使用多個小的專門的介面,而不要使用一個大的總介面。
    具體而言,介面隔離原則體現在:介面應該是內聚的,應該避免“胖”介面。一個類對另外一個類的依賴應該建立在最小的介面上,不要強迫依賴不用的方法,這是一種介面汙染。
    介面有效地將細節和抽象隔離,體現了對抽象程式設計的一切好處,介面隔離強調介面的單一性。而胖介面存在明顯的弊端,會導致實現的型別必須完全實現介面的所有方法、屬性等;而某些時候,實現型別並非需要所有的介面定義,在設計上這是“浪費”,而且在實施上這會帶來潛在的問題,對胖介面的修改將導致一連串的客戶端程式需要修改,有時候這是一種災難。在這種情況下,將胖介面分解為多個特點的定製化方法,使得客戶端僅僅依賴於它們的實際呼叫的方法,從而解除了客戶端不會依賴於它們不用的方法。
    分離的手段主要有以下兩種:1、委託分離,通過增加一個新的型別來委託客戶的請求,隔離客戶和介面的直接依賴,但是會增加系統的開銷。2、多重繼承分離,通過介面多繼承來實現客戶的需求,這種方式是較好的。

詳細介紹。

一、SRP簡介(SRP--Single-Responsibility Principle):
就一個類而言,應該只專注於做一件事和僅有一個引起它變化的原因。

所謂職責,我們可以理解他為功能,就是設計的這個類功能應該只有一個,而不是兩個或更多。也可以理解為引用變化的原因,當你發現有兩個變化會要求我們修改這個類,那麼你就要考慮撤分這個類了。因為職責是變化的一個軸線,當需求變化時,該變化會反映類的職責的變化。
“就像一個人身兼數職,而這些事情相互關聯不大,,甚至有衝突,那他就無法很好的解決這些職責,應該分到不同的人身上去做才對。”

二、舉例說明:
違反SRP原則程式碼: 
modem介面明顯具有兩個職責:連線管理和資料通訊;

Java程式碼  收藏程式碼
  1. interface Modem  
  2. {  
  3.     publicvoid dial(string pno);  
  4.     publicvoid hangup();  
  5.     publicvoid send(char c);  
  6.     publicvoid recv();  
  7. }  


如果應用程式變化影響連線函式,那麼就需要重構:
Java程式碼  收藏程式碼
  1. interface DataChannel  
  2. {  
  3.     publicvoid send(char c);  
  4.     publicvoid recv();  
  5. }  
  6. interface Connection  
  7. {  
  8.     publicvoid dial(string pno);  
  9.     publicvoid hangup();  
  10. }  


三、SRP優點:
消除耦合,減小因需求變化引起程式碼僵化性臭味

四、使用SRP注意點:
1、一個合理的類,應該僅有一個引起它變化的原因,即單一職責; 
2、在沒有變化徵兆的情況下應用SRP或其他原則是不明智的; 
3、在需求實際發生變化時就應該應用SRP等原則來重構程式碼; 
4、使用測試驅動開發會迫使我們在設計出現臭味之前分離不合理程式碼; 
5、如果測試不能迫使職責分離,僵化性和脆弱性的臭味會變得很強烈,那就應該用Facade或Proxy模式對程式碼重構;



一、OCP簡介(OCP--Open-Closed Principle):
Software entities(classes,modules,functions,etc.) should be open for extension, but closed for modification。
軟體實體應當對擴充套件開放,對修改關閉,即軟體實體應當在不修改(在.Net當中可能通過代理模式來達到這個目的)的前提下擴充套件。
Open for extension:當新需求出現的時候,可以通過擴充套件現有模型達到目的。   
Close for modification:對已有的二進位制程式碼,如dll,jar等,則不允許做任何修改。

二、OCP舉例:
1、例子一
假如我們要寫一個工資稅類,工資稅在不同國家有不同計算規則,如果我們不堅持OCP,直接寫一個類封裝工資稅的算稅方法,而每個國家對工資稅的具體實現細節是不盡相同的!如果我們允許修改,即把現在系統需要的所有工資稅(中國工資稅、美國工資稅等)都放在一個類裡實現,誰也不能保證未來系統不會被賣到日本,一旦出現新的工資稅,而在軟體中必須要實現這種工資稅,這個時候我們能做的只有找出這個類檔案,在每個方法里加上日本稅的實現細節並重新編譯成DLL!雖然在.NET的執行環境中,我們只要將新的DLL覆蓋到原有的DLL即可,並不影響現有程式的正常執行,但每次出現新情況都要找出類檔案,新增新的實現細節,這個類檔案不斷擴大,以後維護起來就變的越來越困難,也並不滿足我們以前說的單一職責原則(SRP),因為不同國家的工資稅變化都會引起對這個類的改變動機!如果我們在設計這個類的時候堅持了OCP的話,把工資稅的公共方法抽象出來做成一個介面,封閉修改,在客戶端(使用該介面的類物件)只依賴這個介面來實現對自己所需要的工資稅,以後如果系統需要增加新的工資稅,只要擴充套件一個具體國家的工資稅實現我們先前定義的介面,就可以正常使用,而不必重新修改原有類檔案!

2、例子二
下面這個例子就是既不開放也不封閉的,因為Client和Server都是具體類,如果我要Client使用不同的一個Server類那就要修改Client類中所有使用Server類的地方為新的Server類。
Java程式碼  收藏程式碼
  1. class Client  
  2. {  
  3.    Server server;  
  4.    void GetMessage()  
  5.    {  
  6.       server.Message();  
  7.    }  
  8. }  
  9. class Server  
  10. {  
  11.    void Message();  
  12. }  


下面為修改後符合OCP原則的實現,我們看到Server類是從ClientInterface繼承的,不過ClientInterface卻不叫ServerInterface,原因是我們希望對Client來說ClientInterface是固定下來的,變化的只是Server。這實際上就變成了一種策略模式(Gof Strategy)
Java程式碼  收藏程式碼
  1. interface ClientInterface  
  2. {  
  3.     publicvoid Message();  
  4.     //Other functions
  5. }  
  6. class Server:ClientInterface  
  7. {  
  8.     publicvoid Message();  
  9. }  
  10. class Client   
  11. {  
  12.    ClientInterface ci;  
  13.    publicvoid GetMessage()  
  14.    {  
  15.        ci.Message();  
  16.    }  
  17.    publicvoid Client(ClientInterface paramCi)  
  18.    {  
  19.        ci=paramCi;  
  20.    }  
  21. }  
  22. //那麼在主函式(或主控端)則
  23. publicstaticvoid Main()  
  24. {  
  25.    ClientInterface ci = new Server();  
  26.    //在上面如果有新的Server類只要替換Server()就行了.
  27.    Client client = new Client(ci);  
  28.    client.GetMessage();  
  29. }  


3、例子三
使用Template Method實現OCP:
Java程式碼  收藏程式碼
  1. publicabstractclass Policy  
  2. {  
  3.     privateint[] i ={ 1123412341234132 };  
  4.     public bool Sort()  
  5.     {  
  6.         SortImp();  
  7.     }  
  8.     protected virtual bool SortImp()  
  9.     {  
  10.     }  
  11. }  
  12. class Bubbleimp : Policy  
  13. {  
  14.     protected override bool SortImp()  
  15. 相關推薦

    面向物件五大基本原則

    以前一直認為程式中的類有使用到封裝繼承多型就是面向物件設計,其實不然 封裝,繼承,多型只是面向物件的三大特性,但是在設計程式的時候並不是說類的結構使用到了(或是體現出了)這三個特性就是面向物件, 其實真正的面向物件設計是要符合下面的五大原則, 面向物件的五大基本原則 單

    面向物件五大設計原則以及常見設計模式總結

    儘管本人已經從事OOP程式設計好幾年,但對於OOP程式設計的很多精髓依舊瞭解不深。加之最近專案不緊,特抽出時間總結一些面向物件設計原則以及設計模式的相關內容,加深自己的理解同時也希望可以幫到其他人。 note:程式設計是一門技術更是一門藝術,藝術來源於生活又高於生活。下面介紹的很多東西很多都

    設計模式之面向物件七大基本原則

    PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 概述 在運用面向物件的思想進行軟體設計時,需要遵循的原則一共有7個,他們是: 1. 單一職責原則(Single R

    面向物件基本原則

    一、可維護性 高內聚、低耦合 高內聚,是針對一個元件(類)內部而言,如果一個元件幹了好幾件不相關的事情,那麼元件內部就比較散,出問題是遲早的事情。中原大戰之後,蔣介石表面上統一了各個軍閥,實際上,他們內部之間不夠內聚,一盤散沙。 低耦合,是針對多個元件之間的關係。老死不相往來,是理想國,也就沒有什麼矛盾,但這

    面向物件三大特性、五大基本原則

     三大特性是:封裝,繼承,多型   所謂封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。封裝是面向物件的特徵之一,是物件和類概念的主要特性。 簡單的說,一個類就是一個封裝了資料以及操作這些資料的程式碼的邏輯實體。在一個物件內部,某些程式碼或

    學習Java程式設計面向物件五大基本原則

    Java 是面向物件的高階程式語言,類和物件是 Java 程式的構成核心。圍繞著 Java 類和 Java 物件,有三大基本特性:封裝是 Java 類的編寫規範、繼承是類與類之間聯絡的一種形式、而多型為系統元件或模組之間解耦提供瞭解決方案。 單一職責原則(Single-Resposibility

    面向物件三大基本特性和五大基本原則

    透切理解面向物件三大基本特性是理解面向物件五大基本原則的基礎. 三大特性是:封裝,繼承,多型   所謂封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。封裝是面向物件的特徵之一,是物件和類概念的主要特

    PHP面向物件——三大基本特性與五大基本原則

    三大特性是:封裝、繼承、多型所謂封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。封裝是面向物件的特徵之一,是物件和類概念的主要特性。 簡單的說,一個類就是一個封裝了資料以及操作這些資料的程式碼的邏輯實體。在一

    面向物件的三大基本特性,五大基本原則

    透切理解面向物件三大基本特性是理解面向物件五大基本原則的基礎.三大特性是:封裝,繼承,多型特徵圖封裝封裝最好理解了。封裝是面向物件的特徵之一,是物件和類概念的主要特性。封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。繼承面向物件程式設計 (O

    java面向物件的三大特徵,五大基本原則

    三大特性:封裝,繼承,多型。 1)封裝       將物件的屬性和實現細節隱藏起來,只提供公共的訪問方式。       好處:a。將外界的變化隔離開,使程式具備獨立,安全和穩定性。                  b。便於設計者使用,提高了程式碼的複用性       方式

    面向物件五大基本原則

    面向物件的5大基本設計原則: 單一職責原則(Single-Resposibility Principle)     其核心思想為:一個類,最好只做一件事,只有一個引起它的變化。單一職責原則可以看做是低耦合、高內聚在面向物件原則上的引申,將職責定義為引起變化

    面向對象的三大特性與五大基本原則

    同時 屬性 open for idt emma 這樣的 interface bili 體系 三大特性:封裝,繼承,多態 封裝:就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。封裝是面向對象的特征之一,是對象和類概念

    面向對象的三大特征和五大基本原則

    人物 images 裏氏替換原則 如果 而不是 src 接口分離 實現 -1 http://blog.csdn.net/zhang2531/article/details/52052453 面向對象的編程方法是為了解決系統的可維護性、可擴展性、可重用性。系統的需求是變化的,

    面向對象三大基本特性,五大基本原則

    lose 做到 直接 職責 工程 實體 類結構 ron 依賴 三大特性是:封裝,繼承,多態 封裝:就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。封裝是面向對象的特征之一,是對象和類概念的主要特性。 簡單的說,

    面向對象的五大基本原則

    dip 意思 原因 gof 基本 rom 倒置 接口隔離 使用 1.單一職責原則 一個類應該僅有一個引起它變化的原因 2.開放封閉原則(ocp) 既開放又封閉,對擴展是開放的,對更改是封閉的 3.裏氏替換原則(LSP) 子類可以替換父類並且出現在父類能出現的任何地方

    面向對象五大基本原則

    新的 做到 str 可能 gof 特性 根據 dll 工程師 以前一直認為程序中的類有使用到封裝繼承多態就是面向對象設計,其實不然 封裝,繼承,多態只是面向對象的三大特性,但是在設計程序的時候並不是說類的結構使用到了(或是體現出了)這三個特性就是面向對象, 其實真正的面向對

    PHP-面向對象的三大基本特征和五大基本原則的概念

    gre 簡單 表現 原則 數據 新員工 psi inter ocp 三大特征:封裝、繼承、多態 1、封裝 封裝,就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。 封裝是面向對象的特征之一,是對象和類概念的主要特性。

    20181005 面向對象,三大基本特性,五大基本原則

    data 相同 屬性 級別 表現 職責 進行 分離 包含 透切理解面向對象三大基本特性是理解面向對象五大基本原則的基礎. 三大特性是:封裝,繼承,多態 所謂封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏

    面向對象三大基本特性,五大基本原則

    基本 原來 原則 分開 基本原則 現在 應該 isp 編寫 三大特性是: 封裝 繼承 多態 五大基本原則: 單一職責原則SRP(Single Responsibility Principle) 開放封閉原則OCP(Open-Close Principle) 替換原則

    面向物件基本概念、基本特徵、設計原則

    面向物件:面向物件是一種對現實世界理解和抽象的軟體開發方法——from 百度百科 面向物件程式設計:是一種基於物件的程式設計正規化(英語為Programming paradigm,正規化即模式、方法),它可能包含屬性(knows as at