1. 程式人生 > >面向物件的SOLID原則白話篇

面向物件的SOLID原則白話篇

面向物件的SOLID原則

簡介

縮寫 全稱 中文
S The Single Responsibility Principle 單一責任原則
O The Open Closed Principle 開放封閉原則
L Liskov Substitution Principle 里氏替換原則
I The Interface Segregation Principle 介面分離原則
D The Dependency Inversion Principle 依賴倒置原則

單一職責原則

一個類只應承擔一種責任。換句話說,讓一個類只做一件事。如果需要承擔更多的工作,那麼分解這個類。

舉例

訂單和賬單上都有流水號、業務時間等欄位。如果只用一個類表達,賦予其雙重職責,後果:

  1. 特有屬性和共有屬性相互摻雜,難以理解;
  2. 修改一個場景可能會影響另一個場景。

正確的做法是拆成兩個獨立的類。

開放封閉原則

實體應該對擴充套件是開放的,對修改是封閉的。即,可擴充套件(extension),不可修改(modification)。

舉例

一個商戶接入了多個付款方式,支付寶和微信支付,如果將呼叫支付API的類寫成:

public class PayHandler {

    public Result<T> pay(Param param) {
        if(param.getType() == "ALIPAY") {
            // 支付寶付款呼叫
            ...
        } else if(param.getType() == "WeChatPay") {
           // 微信支付付款呼叫
           ...
        }
    }
}

那麼每次新加一種支付方式,或者修改原有的其中一種支付方式,都要修改PayHandler這個類,可能會影響現有程式碼。

比較好的做法是將不同的行為(支付方式)抽象,如下:

public class PayHandler {

    private Map<String, PayProcessor> processors;

    public Result<T> pay(Param param) {
        PayProcessor payProcessor = processors.get(param.getType());
        // 異常處理略
        return payProcessor.handle(param);
    }
}

interface PayProcessor {
    Result<T> handle(Param param);
}

public class AlipayProcessor implements PayProcessor {
    ...
}

public class WeChatPayProcessor implements PayProcessor {
    ...
}

這樣,新增支付方式只需要新增類,如果使用的是spring等容器,在xml配置對應key-value關係即可;修改已有的支付方式只需要修改對應的類。最大化地避免了對已有實體的修改。

裡式替換原則

一個物件在其出現的任何地方,都可以用子類例項做替換,並且不會導致程式的錯誤。換句話說,當子類可以在任意地方替換基類且軟體功能不受影響時,這種繼承關係的建模才是合理的。

舉例

經典的例子: 正方形不是長方形的子類。原因是正方形多了一個屬性“長 == 寬”。這時,對正方形類設定不同的長和寬,計算面積的結果是最後設定那項的平方,而不是長*寬,從而發生了與長方形不一致的行為。如果程式依賴了長方形的面積計算方式,並使用正方形替換了長方形,實際表現與預期不符。

擴充套件

不能用繼承關係(is-a),但可以用委派關係(has-a)表達。上例中,可以使用正方形類包裝一個長方形類。或者,將正方形和長方形作進一步抽象,使用共有的抽象類。

逸聞

“里氏”指的是芭芭拉·利斯科夫(Barbara Liskov,1939年-),是美國第一個電腦科學女博士,圖靈獎、馮諾依曼獎得主,參與設計並實現了OOP語言CLU,而CLU語言對現代主流語言C++/Java/Python/Ruby/C#都有深遠影響。其專案中提煉出來的資料抽象思想,已成為軟體工程中最重要的精髓之一。(來源: 互動百科

介面分離原則

客戶(client)不應被強迫依賴它不使用的方法。即,一個類實現的介面中,包含了它不需要的方法。將介面拆分成更小和更具體的介面,有助於解耦,從而更容易重構、更改。

舉例

仍以商家接入移動支付API的場景舉例,支付寶支援收費和退費;微信介面只支援收費。

interface PayChannel {
    void charge();
    void refund();
}

class AlipayChannel implements PayChannel {
    public void charge() {
        ...
    }
    
    public void refund() {
        ...
    }
}

class WeChatChannel implements payChannel {
    public void charge() {
        ...
    }
    
    public void refund() {
        // 沒有任何程式碼
    }
}

第二種支付渠道,根本沒有退款的功能,但是由於實現了PayChannel,又不得不將refund()實現成了空方法。那麼,在呼叫中,這個方法是可以呼叫的,實際上什麼都沒有做!

改進

將PayChannel拆成各包含一個方法的兩個介面PayableChannel和RefundableChannel。

依賴倒置原則

  1. 高層次的模組不應依賴低層次的模組,他們都應該依賴於抽象。
  2. 抽象不應依賴於具體實現,具體實現應依賴抽象。

實際上,依賴倒置是實現開閉原則的方法。

舉例

開閉原則的場景仍然可以說明這個問題。以下換一種表現形式。

public class PayHandler {

    public Result<T> pay(Param param) {
        if(param.getType() == "ALIPAY") {
            AlipayProcessor processor = new AlipayProcessor();
            processor.hander(param);
            ...
        } else if(param.getType() == "WeChatPay") {
            WeChatPayProcessor processor = new WeChatPayProcessor();
            processor.hander(param);
           ...
        }
    }
}

public class AlipayProcessor { ... }

public class WeChatPayProcessor { ... }

這種實現方式,PayHandler的功能(高層次模組)依賴了兩個支付Processor(低層次模組)的實現。

擴充套件:IOC和DI

控制反轉(IOC)和依賴注入(DI)是Spring中最重要的核心概念之一,而兩者實際上是一體兩面的。

  • 依賴注入
    • 一個類依賴另一個類的功能,那麼就通過注入,如構造器、setter方法等,將這個類的例項引入。
    • 側重於實現。
  • 控制反轉
    • 建立例項的控制權由一個例項的程式碼剝離到IOC容器控制,如xml配置中。
    • 側重於原理。
    • 反轉了什麼:原先是由類本身去建立另一個類,控制反轉後變成了被動等待這個類的注入。

後記

網路上很多文章中關於SOLID的介紹,語句都不通順,徒增理解難度。如果對基本釋義仍不能領會,可以參考 英文WIKI

相關推薦

面向物件SOLID原則白話

面向物件的SOLID原則 簡介 縮寫 全稱 中文 S The Single Responsibility Principle 單一責任原則 O The Open Closed Principle 開放封閉原則 L Liskov Substitution Principle 里氏替換原則

SOLID面向物件設計原則

  SRP The Single Responsibility Principle 單一責任原則 OCP The Open Closed Principle 開放封閉原則

面向物件設計原則:不要STUPID,堅持GRASP和SOLID

不要STUPID,堅持GRASP和SOLID 聽過SOLID編碼嗎?有人可能會說:這是描述設計原則的一個專業術語,由我們可愛的程式碼整潔之道傳教者鮑勃(羅伯特C. 馬丁)大叔提出,是一組用於指導我們如何寫出“好程式碼”的原則。 在程式設計界充滿了這樣由單詞首字母組成的縮略詞

面向物件設計原則實踐:之五.迪米特原則,介面隔離原則

六、迪米特(第三者互動)原則 1. 定義 每一個軟體單位對其他的單位都只有最少的知識,而且侷限於那些與本單位密切相關的軟體單位。   2. 分析 1) 迪米特法則就是指一個軟體實體應當儘可能少的與其他實體發生相互作用。 這樣,當一個模組修改時,就會盡量少的影響其他的

面向物件設計原則實踐:之四.里氏代換原則

五、里氏代換原則(LSP--Liskov Substitution Principle) 1. 定義 a). 如果對每一個型別為S的物件o1,都有型別為T的物件o2, 使得以T定義的所有程式P在所有的物件o1都代換成o2時,程式P的行為沒有變化, 那麼型別S是型別T的子型別。 b

面向物件設計原則 開放封閉原則(Open Closed Principle)

開放封閉原則(OCP,Open Closed Principle)是所有面向物件原則的核心。   軟體設計本身所追求的目標就是封裝變化、降低耦合,而開放封閉原則正是對這一目標的最直接體現。 其他的設計原則,很多時候是為實現這一目標服務的,例如以里氏替換原則實現最佳的、正確的繼承層次,就能保證不

面向物件設計原則 依賴倒置原則(Dependency Inversion Principle)

依賴倒置原則(Dependence Inversion Principle)是程式要依賴於抽象介面,不要依賴於具體實現。 簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合。   面向過程的開發

面向物件設計原則 介面分離原則(Interface Segregation Principle)

介面隔離原則   使用多個專門的介面,而不使用單一的總介面,即客戶端不應該依賴那些它不需要的介面。   從介面隔離原則的定義可以看出,他似乎跟SRP有許多相似之處。 是的其實ISP和SRP都是強調職責的單一性, 介面隔離原則告訴我們在定義介面的時候要根據職責定義“較小”的介面

面向物件設計原則之合成複用原則

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

面向物件設計原則之介面隔離原則

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

面向物件設計原則之依賴倒轉原則

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

面向物件設計原則之迪米特法則

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Python開發【第七】:面向物件(進階

上一篇《Python 面向物件(初級篇)》文章介紹了面向物件基本知識: 面向物件是一種程式設計方式,此程式設計方式的實現是基於對 類 和 物件 的使用 類 是一個模板,模板中包裝了多個“函式”供使用(可以講多函式中公用的變數封裝到物件中) 物件,根據模板

面向物件六大原則之單一

單一職責原則-SRP(Single Responsibility Principle) 通俗的說,即一個類只負責一項職責 如:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時有可能會導致原本執行正常的職責P2功能發生故障。 如:對資料庫的增刪查改,對資料

C#設計模式前奏-面向物件設計原則

          在學習設計模式之前,面向物件設計原則是必須要了解的東西。因為大多數設計模式都遵循這些設計原則中的一種或者多種。今天就帶大家一起去學習學習七類面向設計原則。首先列出常用的7中面向物件

面向物件七大原則詳解

單一職責原則    定義:一個類只負責一個領域的相應職責。 開閉原則 定義:軟體實體應對擴充套件開放,而對修改關閉。 里氏替換原則   定義:所有引用基類的物件能夠透明的使用其子類的物件。 依賴倒轉原則   定義:抽象

java程式設計師應當知道的10個面向物件設計原則

面向物件設計原則是OOPS程式設計的核心, 但我見過的大多數Java程式設計師熱心於像Singleton (單例) 、 Decorator(裝飾器)、Observer(觀察者) 等設計模式,而沒有把足夠多的注意力放在學習面向物件的分析和設計上面。學習面向物件程式設計像“抽象”

【面試】面向物件相關-這一全瞭解

1、什麼是面向物件,什麼是面向過程。面向物件的三大基本特徵和五大基本原則是什麼? 解: 什麼是面向過程? 把問題分解成一個一個步驟,每個步驟用函式實現,依次呼叫即可。就是說,在進行面向過程程式設計的時候,不需要考慮那麼多,上來先定義一個函式,然後使用各種諸如if-els

面向物件設計原則-類庫設計原則

1.共同重用原則(CCP):一組介面中應該是共同重用的。如果重用了這組中 的一個類,那麼就要重用包中的所有的類。相互之間沒有緊密聯絡的類不應該在同一組中。 這個原則強調了分類,就具有相同關係或者關聯比較緊密的類應該分到一組中,方便修改和客戶端的呼叫。 2.共同封閉原則:類庫中的類

java面向物件原則

 單一職責原則:一個類只做它該做的事情。(單一職責原則想表達的就是"高內聚",寫程式碼最終極的原則只有六個字"高內聚、低耦合",就如同葵花寶典或辟邪劍譜的中心思想就八個字"欲練此功必先自宮",所謂的高內聚就是一個程式碼模組只完成一項功能,在面向物件中,如果只讓一個類完成它該做的事,而不涉及