門戶網(wǎng)站開發(fā)框架qq群怎么優(yōu)化排名靠前
1.背景
2002 年羅伯特·C.馬丁給“接口隔離原則”的定義是:客戶端不應該被迫依賴于它不使用的方法(Clients should not be forced to depend on methods they do not use)。該原則還有另外一個定義:一個類對另一個類的依賴應該建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface)。
2.概念
接口隔離原則(Interface Segregation Principle,ISP)要求程序員盡量將臃腫龐大的接口拆分成更小的和更具體的接口,讓接口中只包含客戶感興趣的方法。
通俗的講:
-
一個類對另外一個類的依賴性應當是建立在最小的接口上的;
-
一個接口代表一個角色,不應當將不同的角色都交給一個接口。沒有關(guān)系的接口合并在一起,形成一個臃腫的大接口,這是對角色和接口的污染;
-
使用多個專門的接口比使用單一的總接口要好;
-
不要強迫客戶使用它們不用的方法,如果強迫用戶使用它們不使用的方法,那么這些客戶就會面臨由于這些不使用的方法的改變所帶來的改變;
接口隔離原則和單一職責原則很像,都是為了提高類的內(nèi)聚性、降低它們之間的耦合性,體現(xiàn)了封裝的思想,但兩者是不同的:
-
單一職責原則注重的是職責,而接口隔離原則注重的是對接口依賴的隔離。
-
單一職責原則主要是約束類,它針對的是程序中的實現(xiàn)和細節(jié);接口隔離原則主要約束接口,主要針對抽象和程序整體框架的構(gòu)建。
應用接口隔離原則的建議:
-
接口盡量小,但是要有限度,既不能是大而全的接口也不能是一個方法一個接口,這樣就失去了面向抽象的意義,應該按照功能的密不可分來定義接口,而且應該是動態(tài)的,因為隨著業(yè)務(wù)發(fā)展功能需求是有變化的,所以我們在設(shè)計的時候要考慮留好提前量,避免抽象的變化;
-
為依賴接口的類定制服務(wù),只提供調(diào)用者需要的方法,屏蔽不需要的方法;
-
了解環(huán)境,拒絕盲從,每個項目或產(chǎn)品都有選定的環(huán)境因素,環(huán)境不同,接口拆分的標準就不同深入了解業(yè)務(wù)邏輯;
-
提高內(nèi)聚,減少對外交互,使接口用最少的方法去完成最多的事情;
3.案例分析
需求:我們要開發(fā)一個學生成績管理項目,包含插入成績、刪除成績、修改成績、計算總分、計算均分、打印成績信息、査詢成績信息等功能;如果將這些功能全部放到一個接口中顯然不太合理,正確的做法是將它們分別放在輸入模塊、統(tǒng)計模塊和打印模塊等 3 個模塊中。
/// <summary>/// 輸入模塊/// </summary>public interface IInputModule{/// <summary>/// 添加成績/// </summary>void Insert();/// <summary>/// 刪除成績/// </summary>void Delete();/// <summary>/// 修改成績/// </summary>void Modify();}/// <summary>/// 統(tǒng)計模塊/// </summary>public interface ICountModule{/// <summary>/// 計算總分/// </summary>void CountTotalScore();/// <summary>/// 計算平均分/// </summary>void CountAverage();}/// <summary>/// 打印模塊/// </summary>public interface IPrintModule{/// <summary>/// 打印學生信息/// </summary>void PrintStudentInfo();/// <summary>/// 查詢學生信息/// </summary>void QueryStudentInfo();}/// <summary>/// 實現(xiàn)類/// </summary>public class StudentSoreList : IInputModule, ICountModule, IPrintModule{private StudentSoreList(){}public static IInputModule GetInputModule(){return (IInputModule)new StudentSoreList();}public static ICountModule GetCountModule(){return (ICountModule)new StudentSoreList();}public static IPrintModule GetPrintModule(){return (IPrintModule)new StudentSoreList();}public void Insert(){Console.WriteLine("輸入模塊的Insert()方法被調(diào)用!");}public void Delete(){Console.WriteLine("輸入模塊的Delete()方法被調(diào)用!");}public void Modify(){Console.WriteLine("輸入模塊的Modify()方法被調(diào)用!");}public void CountTotalScore(){Console.WriteLine("統(tǒng)計模塊的CountTotalScore()方法被調(diào)用!");}public void CountAverage(){Console.WriteLine("統(tǒng)計模塊的CountAverage()方法被調(diào)用!");}public void PrintStudentInfo(){Console.WriteLine("打印模塊的PrintStudentInfo()方法被調(diào)用!");}public void QueryStudentInfo(){Console.WriteLine("打印模塊的QueryStudentInfo()方法被調(diào)用!");}}{//ISP:接口隔離原則IInputModule inputModule = StudentSoreList.GetInputModule();inputModule.Insert();ICountModule countModule = StudentSoreList.GetCountModule();countModule.CountTotalScore();IPrintModule printModule = StudentSoreList.GetPrintModule();printModule.PrintStudentInfo();}
4.優(yōu)缺點
優(yōu)點:
-
將臃腫龐大的接口分解為多個粒度小的接口,可以預防外來變更的擴散,提高系統(tǒng)的靈活性和可維護性;
-
接口隔離提高了系統(tǒng)的內(nèi)聚性,減少了對外交互,降低了系統(tǒng)的耦合性;
-
如果接口的粒度大小定義合理,能夠保證系統(tǒng)的穩(wěn)定性;但是,如果定義過小,則會造成接口數(shù)量過多,使設(shè)計復雜化;如果定義太大,靈活性降低,無法提供定制服務(wù),給整體項目帶來無法預料的風險;
-
使用多個專門的接口還能夠體現(xiàn)對象的層次,因為可以通過接口的繼承,實現(xiàn)對總接口的定義;
-
能減少項目工程中的代碼冗余。過大的大接口里面通常放置許多不用的方法,當實現(xiàn)這個接口的時候,被迫設(shè)計冗余的代碼;
缺點:
-
需要掌握接口細分的程度,如果太細,會造成接口膨脹,增加系統(tǒng)的復雜性;