1. 程式人生 > 實用技巧 >單一職責原則

單一職責原則

一、前言

單一職責原則是對類來說的,即一個類應該只負責一項具體的職責.如類 A 負責兩個不同職責:職責 1、職責 2.當職責 1 需求變更而改變 A 時,可能造成職責 2 執行錯誤,所以需要將類 A 的粒度分解為 A1、A2

單一職責原則注意事項和細節
1、降低類的複雜度,一個類只負責一項職責
2、提高類的可讀性,可維護性
3、降低變更引起的風險
4、通常情況下,我們應當遵守單一職責原則,只有邏輯足夠簡單,才可以在程式碼級違反單一職責原則,只有類中方法數量足夠少,可以在方法級別保持單一職責原則

二、案例分析(以交通工具執行方式為例)

1、方式一

// 測試類
public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("car");
        vehicle.run("railway");
        vehicle.run("steamer");
        vehicle.run("airplane");
    }
}

// 交通工具類
class Vehicle{
    public void run(String vehicleType){
        System.out.println(vehicleType + "在地上執行...");
    }
}

// 測試結果
car在地上執行...
railway在地上執行...
steamer在地上執行...
airplane在地上執行...

方式一程式碼比較簡單,但是我們發現一個問題, car 、railway 在地上執行時符合我們邏輯的,但是 steamer、airplane 在地上執行,這明顯不符合我們的思維邏輯,它違反了單一職責,即一個類應該只完成一項具體的職責,而我們這裡的 Vehicle 卻完成了多項職責,所以我們嘗試著改進

2、方式二

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("railway");
        SeaVehicle seaVehicle = new SeaVehicle();
        seaVehicle.run("steamer");
        AirVehicle airVehicle = new AirVehicle();
        airVehicle.run("airplane");
    }
}

class RoadVehicle{
    public void run(String vehicleType){
        System.out.println(vehicleType + "在地上執行...");
    }
}

class SeaVehicle{
    public void run(String vehicleType){
        System.out.println(vehicleType + "在海上執行...");
    }
}

class AirVehicle{
    public void run(String vehicleType){
        System.out.println(vehicleType + "在空中執行...");
    }
}

// 測試結果
railway在地上執行...
steamer在海上執行...
airplane在空中執行...

方式二就嚴格的遵循了單一職責原則,不同型別的交通工具執行方式進行類級別的拆分,每個類只負責完成自己對應的執行方式,但是呢,這裡有一個缺點,我們這裡類的方法很少,只有一個 run 方法,但是我們需要使用的時候建立了三個類,並且呢使用不同的交通工具的時候還建立了三次物件,這樣的花銷是很大的,所以我們還可以改進

3、方式三

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.runWithRoad("railway");
        vehicle.runWithSea("steamer");
        vehicle.runWithAir("airplane");
    }
}

class Vehicle{
    public void runWithRoad(String vehicleType){
        System.out.println(vehicleType + "在地上執行...");
    }

    public void runWithSea(String vehicleType){
        System.out.println(vehicleType + "在海上執行...");
    }

    public void runWithAir(String vehicleType){
        System.out.println(vehicleType + "在空中執行...");
    }
}

// 測試結果
railway在地上執行...
steamer在海上執行...
airplane在空中執行...

方式三雖然不是完全遵循單一職責原則,但是它卻是在方法級別上遵循了單一職責原則,我們之所以這樣設計是因為它這個類裡面的方法很少,如果 Vehicle 類中方法比較多的情況下還採用方式三的設計原則,就會造成Vehicle 這個類裡面的方法很多,設計上就會很臃腫,所以方法較多的情況下建議使用方式二