1. 程式人生 > 其它 >軟體架構設計原則之單一職責原則

軟體架構設計原則之單一職責原則

單一職責(Simple Responsibility Pinciple,SRP)是指不要存在多於一個導致類變更的原因。假設我們有一個類負責兩個職責,一旦發生需求變更,修改其中一個職責的邏輯程式碼,有可能導致另一個職責的功能發生故障。這樣一來,這個類就存在兩個導致類變更的原因。如何解決這個問題呢?將兩個職責用兩個類來實現,進行解耦。後期需求變更維護互不影響。這樣的設計,可以降低類的複雜度,提高類的可讀性,提高系統的可維護性,降低變更引起的風險。總體來說,就是一個類、介面或方法只負責一項職責。

接下來,我們來看程式碼例項,還是用課程舉例,我們的課程有直播課和錄播課。直播課不能快進和快退,錄播課程可以任意地反覆觀看,功能職責不一樣。還是先建立一個Course類:

public classCourse {

public voidstudy(String courseName){

if("直播課".equals(courseName)){

System.out.println(courseName + "不能快進");

}else{

System.out.println(courseName + "可以反覆回看");

}

}

}

看呼叫程式碼:

public static voidmain(String[] args) {

Course course = newCourse();

course.study("直播課");

course.study("錄播課");

}

從上面的程式碼來看,Course類承擔了兩種處理邏輯。假如現在要對課程進行加密,直播課程和錄播課程的加密邏輯不一樣,必須修改程式碼。而修改程式碼的邏輯勢必會相互影響,容易帶來不可控的風險。我們對職責進行解耦,來看程式碼,分別建立兩個類:LiveCourse和ReplayCourse。

LiveCourse類的程式碼如下:

public classLiveCourse {

public voidstudy(String courseName){

System.out.println(courseName + "不能快進看");

}

}
ReplayCourse類的程式碼如下:

public classReplayCourse {

public voidstudy(String courseName){

System.out.println(courseName + "可以反覆回");

}

}

呼叫程式碼如下:

public static voidmain(String[] args) {

LiveCourse liveCourse = newLiveCourse();

liveCourse.study("直播課");



ReplayCourse replayCourse = newReplayCourse();

replayCourse.study("錄播課");

}

業務繼續發展,課程要做許可權。沒有付費的學員可以獲取課程基本資訊,已經付費的學員可以獲得視訊流,即學習許可權。那麼在控制課程層面上至少有兩個職責。我們可以把展示職責和管理職責分離開來,都實現同一個抽象依賴。設計一個頂層介面,建立ICourse介面:

public interfaceICourse {

//獲得基本資訊

String getCourseName();

//獲得視訊流

byte[]getCourseVideo();

//學習課程

voidstudyCourse();

//退款

voidrefundCourse();

}

我們可以把這個介面拆成兩個介面:ICourseInfo和ICourseManager。

ICourseInfo介面的程式碼如下:

public interfaceICourseInfo {

String getCourseName();

byte[]getCourseVideo();

}

ICourseManager介面的程式碼如下:

public interfaceICourseManager {

voidstudyCourse();

voidrefundCourse();

}

來看一下類圖,如下圖所示。

下面我們來看一下方法層面的單一職責設計。有時候我們會偷懶,把一個方法寫成下面這樣:

private voidmodifyUserInfo(String userName,String address){

userName = "Tom";

address = "Changsha";

}

還可能寫成這樣:

private voidmodifyUserInfo(String userName,String... fileds){

userName = "Tom";

// address = "Changsha";

}

private voidmodifyUserInfo(String userName,String address,booleanbool){

if(bool){


}else{


}

userName = "Tom";

address = "Changsha";

}

顯然,上面的modifyUserInfo()方法承擔了多個職責,既可以修改userName,也可以修改address,甚至更多,明顯不符合單一職責。我們做如下修改,把這個方法拆成兩個方法:

private voidmodifyUserName(String userName){

userName = "Tom";

}

private voidmodifyAddress(String address){

address = "Changsha";

}

修改之後,開發起來簡單,維護起來也容易。我們在實際開發中會有專案依賴、組合、聚合這些關係,還有專案的規模、週期、技術人員的水平、對進度的把控,很多類都不符合單一職責。但是,我們在編寫程式碼的過程,儘可能地讓介面和方法保持單一職責,對專案後期的維護是有很大幫助的。