<sub id="gqw76"><listing id="gqw76"></listing></sub>
      <sub id="gqw76"><listing id="gqw76"></listing></sub>

    1. <form id="gqw76"><legend id="gqw76"></legend></form>
    2. 設計模式六大原則(四)----接口隔離原則

      一. 接口隔離原則的定義

      Clients should not be forced to depend upon interfaces that they don't use.

      客戶端只依賴于它所需要的接口;它需要什么接口就提供什么接口,把不需要的接口剔除掉。

      The dependency of one class to another one should depend on the smallest possible interface.

      類間的依賴關系應建立在最小的接口上。

      也就是說: 接口盡量細化,接口中的方法盡量少

      二. 接口隔離原則和單一職責原則

      從功能上來看,接口隔離原則和單一職責原則都是為了提高類的內聚, 降低類之間的耦合, 體現了封裝的思想。但二者還是有區別的。

      (1)從原則約束來看: 接口隔離原則更關注的是接口依賴程度的隔離;而單一職責原則更加注重的是接口職責的劃分。

      (2)從接口的細化程度來看: 單一職責原則對接口的劃分更加精細,而接口隔離原則注重的是相同功能的接口的隔離。接口隔離里面的最小接口有時可以是多個單一職責的公共接口。

      (3)單一職責原則更加偏向對業務的約束: 接口隔離原則更加偏向設計架構的約束。這個應該好理解,職責是根據業務功能來劃分的,所以單一原則更加偏向業務;而接口隔離更多是為了“高內聚”,偏向架構的設計。

      三. 接口隔離原則的優點

      接口隔離原則是為了約束接口、降低類對接口的依賴性,遵循接口隔離原則有以下 5 個優點。

      1. 將臃腫龐大的接口分解為多個粒度小的接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。
      2. 接口隔離提高了系統的內聚性,減少了對外交互,降低了系統的耦合性。
      3. 如果接口的粒度大小定義合理,能夠保證系統的穩定性;然而,如果定義過小,則會造成接口數量過多,使設計復雜化;如果定義太大,靈活性降低,無法提供定制服務,給整體項目帶來無法預料的風險。
      4. 使用多個專門的接口能夠體現對象的層次,因為可以通過接口的繼承,實現對總接口的定義。
      5. 能減少項目工程中的代碼冗余。過大的大接口里面通常放置許多不用的方法,當實現這個接口的時候,被迫設計冗余的代碼。

      四. 接口隔離原則的實現方法

      在具體應用接口隔離原則時,應該根據以下幾個規則來衡量。
      1)接口要盡量小
      不能出現Fat Interface;但是要有限度,首先不能違反單一職責原則(不能一個接口對應半個職責)。

      2)接口要高內聚
      在接口中盡量少公布public方法。
      接口是對外的承諾,承諾越少對系統的開發越有利。

      3)定制服務
      只提供訪問者需要的方法。例如,為管理員提供IComplexSearcher接口,為公網提供ISimpleSearcher接口。

      4)接口的設計是有限度的
      了解環境,拒絕盲從。每個項目或產品都有選定的環境因素,環境不同,接口拆分的標準就不同, 需要深入了解業務邏輯。

      五. 接口隔離原則的建議

      1. 一個接口只服務于一個子模塊或業務邏輯;
      2. 通過業務邏輯壓縮接口中的public方法;
      3. 已被污染了的接口,盡量去修改;若變更的風險較大,則采用適配器模式轉化處理;
      4. 拒絕盲從

      五. 案例分析

      下面以學生成績管理為例來說明接口隔離原則:

      分析:學生成績管理程序一般包含查詢成績、新增成績、刪除成績、修改成績、計算總分、計算平均分、打印成績信息等功能,通常我們會怎么做呢?

      一: 最初的設計

      通常我們設計接口的方式如下:

      public interface IStudentScore {
          // 查詢成績
          public void queryScore();
      
          // 修改成績
          public void updateScore();
      
          // 添加成績
          public void saveScore();
      
          // 刪除成績
          public void delete();
      
          // 計算總分
          public double sum();
      
          // 計算平均分
          public double avg();
      
          // 打印成績單
          public void printScore();
      
      }
      

      我們會吧所有的功能都放在一個接口里面. 這會產生什么樣的問題呢?
      首先, 接口的方法很多, 不利于擴展. 比如: 學生只有查看成績,打印成績單的權限, 沒有增刪改的權限; 老師擁有所有的權限.
      查詢成績單:

      package com.lxl.www.designPatterns.sixPrinciple.interfaceSegregationPrinciple.score;
      
      public class QueryScore implements IStudentScore{
          @Override
          public void queryScore() {
              // 查詢成績
          }
      
          @Override
          public void updateScore() {
               // 沒有權限
          }
      
          @Override
          public void saveScore() {
              // 沒有權限
          }
      
          @Override
          public void delete() {
              // 沒有權限
          }
      
          @Override
          public double sum() {
              // 沒有權限
              return 0;
          }
      
          @Override
          public double avg() {
              // 沒有權限
              return 0;
          }
      
          @Override
          public void printScore() {
              //打印成績單
          }
      }
      

      操作成績單

      package com.lxl.www.designPatterns.sixPrinciple.interfaceSegregationPrinciple.score;
      
      public class Operate implements IStudentScore{
          @Override
          public void queryScore() {
              
          }
      
          @Override
          public void updateScore() {
      
          }
      
          @Override
          public void saveScore() {
      
          }
      
          @Override
          public void delete() {
      
          }
      
          @Override
          public double sum() {
              return 0;
          }
      
          @Override
          public double avg() {
              return 0;
          }
      
          @Override
          public void printScore() {
      
          }
      }
      
      

      可以看出問題. 查詢成績單, 我們只會用到兩個方法, 可是因為實現了接口, 不得不重寫所有的方法.
      如果這時候增加需求--發送給家長, 只有老師才有這個權限, 學生沒有這個權限. 可是, 在接口中增加一個抽象方法以后, 所有的實現類都要重寫這個方法. 這就違背了開閉原則.

      2. 使用接口隔離原則的設計

      采用接口隔離原則設計的接口, UML圖如下:

      public interface IQueryScore {
          // 查詢成績
          public void queryScore();
      
          // 打印成績單
          public void printScore();
      }
      
      public interface IOperateScore {
      
          // 修改成績
          public void updateScore();
      
          // 添加成績
          public void saveScore();
      
          // 刪除成績
          public void delete();
      
          // 計算總分
          public double sum();
      
          // 計算平均分
          public double avg();
      
      }
      
      
      public class StudentOperate implements IQueryScore{
          @Override
          public void queryScore() {
              // 查詢成績
          }
      
          @Override
          public void printScore() {
              //打印成績單
          }
      }
      
      
      public class TeacherOperate implements IQueryScore, IOperateScore{
          @Override
          public void queryScore() {
      
          }
      
          @Override
          public void updateScore() {
      
          }
      
          @Override
          public void saveScore() {
      
          }
      
          @Override
          public void delete() {
      
          }
      
          @Override
          public double sum() {
              return 0;
          }
      
          @Override
          public double avg() {
              return 0;
          }
      
          @Override
          public void printScore() {
      
          }
      }
      
      

      我們將原來的一個接口進行了接口拆分. 分為查詢接口和操作接口. 這樣學生端就不需要重寫和他不相關的接口了.

      如果將這些功能全部放到一個接口中顯然不太合理,正確的做法是將它們分別放在輸入模塊、統計模塊和打印模塊等 3 個模塊中,其類圖如圖 1 所示



      posted @ 2021-06-07 08:53  盛開的太陽  閱讀(322)  評論(0編輯  收藏  舉報
      最新chease0ldman老人|无码亚洲人妻下载|大香蕉在线看好吊妞视频这里有精品www|亚洲色情综合网

        <sub id="gqw76"><listing id="gqw76"></listing></sub>
        <sub id="gqw76"><listing id="gqw76"></listing></sub>

      1. <form id="gqw76"><legend id="gqw76"></legend></form>