日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

介紹

SOLID是什么,它是如何幫助我們寫更好的代碼的?

SOLID原則由以下5個概念組成:

  1. Single Responsibility(單一職責)
  2. Open/Closed(開閉)
  3. Liskov Substitution(里氏替換)
  4. Interface Segregation(接口隔離)
  5. Dependency Inversion(依賴反轉)

 

簡單來說,這些原則幫助我們創造更易維護,易于理解和靈活的軟件。因此,隨著我們應用的擴大,我們可以降低其復雜性,并在以后為我們省去很多麻煩。

 

深入說明

單一職責原則

像我們從字面意思看到的一樣,該原則指出,一個類僅應承擔一種責任。此外,它應該只有一個改變的理由(不能同時有很多理由來修改它)。

那么,這個原則是怎么幫助我們寫更好的軟件的?讓我們先看一下它的優點:

  1. 易測試 - 因為職責單一,所以擁有更少的測試用例
  2. 低耦合 - 單個類中較少的功能將具有較少的依賴關系
  3. 易于組織 - 更容易編寫代碼邏輯

 

下面我們以代碼示例說明:

我們用Book類代表一本書,其屬性包括:書名(name),作者(author)和內容(text)

/**
 *  實體:書
 */
public class Book {

    private String name;
    private String author;
    private String text;

    /**
     *  文本替換
     * @param word
     * @return
     */
    public String replaceWordInText(String word){
        return text.replaceAll(word, text);
    }

    /**
     *  是否包含指定的文本
     * @param word
     * @return
     */
    public boolean isWordInText(String word){
        return text.contains(word);
    }
}

現在我們的程序運行的很好,我們能存儲任意的書的內容。但是我們無法將書的內容打印出來,無法閱讀該怎么辦?那么,我們就在新增一個打印內容的方法,如:

void printTextToConsole(){
    // 輸出文本
}

好的,現在已經可以實現打印內容了。但是,我們這樣就違背了“單一職責”(書本身不與打印有什么關系)。為了解決我們的問題,需要實現一個單獨的類,該類僅與打印書籍有關:

/**
 * 書籍打印
 */
public class BookPrinter {

    /**
     *  打印到控制臺
     * @param text
     */
    void printTextToConsole(String text){
        // printing the text
    }

    /**
     *  打印到其他媒介
     * @param text
     */
    void printTextToAnotherMedium(String text){
        // do something
    }
}

上面的類不僅與書籍本身解耦,而且能夠實現通過各種媒介進行打印內容,本身又是一個職責單一的案例(打印)。

 

開閉原則

簡單來說,一個類應對擴展是打開的,對修改是關閉的(open for extension, closed for modification)。這樣一來,我們就可以避免修改現有代碼,從而引入新的潛在的問題。當然有個特例,就是如果現有代碼中存在已有bug,我們還是應該去解決它的。

 

比如現在有一個吉他,可以實現基本功能的彈奏:

/**
 *  吉他
 */
public class Guitar {
    private String make;
    private String model;
    private int volume;
}

但是用了一段時間后,覺得有點無聊想增加一些音節,讓它用起來更加的搖滾。

我們如果直接在原有的Guitar類上修改,可能會把原有的功能破壞掉從而引入新的問題,所以根據“開閉原則”,我們應該在原有基礎上進行擴展而不是修改:

/**
 *  更酷炫的音節
 */
public class SuperCoolGuitarWithFlames extends Guitar {
    private String flameColor;
}

通過擴展實現,我們可以保證現有的功能不會受到破壞。

里氏替換原則

這個原則字面意思較難理解,簡單來說就是,如果一個類A是類B的子類,那么我們在不中斷程序行為的情況下可以把B替換成A,而不影響程序原有的功能。

我們用代碼示例說明:

/**
 *  車
 */
public interface Car {
    /**
     *  打開引擎
     */
    void turnOnEngine();

    /**
     *  加速
     */
    void accelerate();
}

我們定義了一個接口,里面有兩個方法,可以實現引擎打開和車加速功能。

下面來看下具體的實現類:

/**
 *  摩托車
 */
public class MotorCar {
    private Engine engine;
    
    public void turnOnEngine() {
        //turn on the engine!
        engine.on();
    }
    public void accelerate() {
        //move forward!
        engine.powerOn(1000);
    }
}

可以看出摩托車屬于車的一種,實現了打開引擎和加速能力,我們繼續看其他實現:

/**
 *  電車
 */
public class ElectricCar {
    public void turnOnEngine() {
        throw new AssertionError("I don't have an engine!");
    }
    public void accelerate() {
        //this acceleration is crazy!
    }
}

可以看出,上面的電車雖然實現了Car,但是它沒有引擎,所以不具有打開引擎的功能,那么這個就改變了程序的行為,違背了我們說的“里氏替換原則”。

接口隔離原則

簡單來說,就是將大的接口切分為更小的接口,這樣我們就可以確保實現類只需要關心它們感興趣的方法。

舉個例子,假如我們在動物園工作,具體是熊的“看護人”,那么可以這樣定義:

public interface BearKeeper {
    /**
     *  給熊洗澡
     */
    void washTheBear();

    /**
     *  給熊喂食
     */
    void feedTheBear();

    /**
     *  撫摸熊
     */
    void petTheBear();
}

我們可以開心的喂養熊,但是撫摸熊可能有危險,但是我們的接口定義的相當大,我們別無選擇。那么,現在我們將接口拆分一下:

public interface BearCleaner {
    void washTheBear();
}
public interface BearFeeder {
    void feedTheBear();
}
public interface BearPetter {
    void petTheBear();
}

通過拆分,我們就可以自由實現我們感興趣的方法,

public class BearCarer implements BearCleaner, BearFeeder {
    public void washTheBear() {
        
    }
    public void feedTheBear() {
     
    }
}

我們可以將撫摸熊的“福利”給那么膽大或瘋狂的人:

public class CrazyPerson implements BearPetter {
    public void petTheBear() {
        //Good luck with that!
    }
}

依賴反轉

這個原則主要是為了解耦。代替低級模塊依賴高級模塊,二者都應該依賴抽象。

舉個例子,假如我們現有一臺windows98電腦:

public class Windows98machine {}

但是沒有顯示器和鍵盤對我們來說有什么用呢?于是我們給這臺電腦新增顯示器和鍵盤:

public class Windows98Machine {
    private final StandardKeyboard keyboard;
    private final Monitor monitor;
    public Windows98Machine() {
        monitor = new Monitor();
        keyboard = new StandardKeyboard();
    }
}

上面代碼運行的很好,我們的電腦已經實現了顯示器和鍵盤,那么問題解決了嗎?沒有,我們又把這三個類緊密結合在一起了。這不僅使Windows98Machine難以測試,而且還失去了將StandardKeyboard替換為其他類的能力。

讓我們把Keyboard抽象出來:

public interface Keyboard { }
public class Windows98Machine{
    private final Keyboard keyboard;
    private final Monitor monitor;
    public Windows98Machine(Keyboard keyboard, Monitor monitor) {
        this.keyboard = keyboard;
        this.monitor = monitor;
    }
}
public class StandardKeyboard implements Keyboard { }

現在Windows98Machine就與StandardKeyboard解耦了,通過依賴反轉(依賴抽象而不是具體類)完成了解耦。

 

總結

在本文中我們深入研究了面向對象的SOLID原則,并通過代碼示例說明其原理和實現。深入設計原則-SOLID

分享到:
標簽:SOLID
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定