2010-06-24 78 views
4

可以說我有下面的一組接口....如何重構胖界面?

public interface IStart 
     { 
      void M1(); 
      bool IsWorking { get; } 
     } 

    public interface IStartStop : IStart 
     { 
      void M2(); 
        event EventHandler DoM1; 
      event EventHandler DoM2; 
     } 
    public interface IPreferencesReader : IStartStop, IDisposable 
     { 
      string CustomColumnDefinition  {get;} 
       bool UsePricelevelDetection {get;} 
      void InitializePreferences(); 
     } 

現在,如果我要實現我的IPreferencesReader類會是什麼樣子下面。這是一個胖接口的例子,其中我必須提供實現我可能不需要的方法。

public class PreferencesReaderBase : IPreferencesReader 
    { 
     public void M1() 
     { 
      throw new NotImplementedException(); 
     } 

     public bool IsWorking 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public void M2() 
     { 
      throw new NotImplementedException(); 
     } 

     public event EventHandler DoM1; 
     public event EventHandler DoM2; 

     public void Dispose() 
     { 
      throw new NotImplementedException(); 
     } 

     public string CustomColumnDefinition 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public bool UsePricelevelDetection 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public void InitializePreferences() 
     { 
      DoSomeInitialization(); 
     } 
    } 

我可以應用這種情況下的任何模式,以重構它嗎?

編輯:我不能沒有這個層次,因爲在不能刪除任何接口。

感謝您的關注。

+0

我認爲你的IPreferencesReader做了太多事情:CustomColumnDefinition聽起來並不像讀取偏好那樣,例如,它聽起來應該是在子類上。 – 2010-06-24 14:28:56

回答

1

使用「適配器」的格局 - 而不是one,維基百科標識,所以也許我的術語是非標準的 - 但像Java的MouseAdapter

接收抽象適配器類 鼠標事件。這個類的 中的方法是空的。該類 作爲創建 偵聽器對象的便利而存在。

...

擴展此類創建 的MouseEvent偵聽器並重寫 方法感興趣的事件。 (如果實現MouseListener 界面,你必須定義所有的 在它的方法。此抽象類 定義了他們所有的空方法,所以 你只需要針對所關心的事件重寫方法 。)

只需編寫一個抽象類來保存所有必要接口的空實現;對其進行子類化並覆蓋與您的需求相關的方法。

全胖界面依然存在;它仍然由你的類實現(通過繼承) - 但是你的類的代碼將只包含重要的東西。

2

您不一定需要提供工作實現。在你的示例中,它看起來像你的IPreferencesReader不需要IStartStop,所以你可以簡單地刪除它的包含?

如果要隱藏從實現類型的接口方法(即,你不會看到它PreferencesReaderBase對象)可以實現顯式接口:

void IStart.Start() { } 

然後您將只能夠通過將您的PreferencesReaderBase引用轉換爲IStart引用來調用這些接口方法。

+0

刪除了工作(實際)代碼。 關於顯式實現,這不會解決我的問題。由於界面仍然很胖(要求在用戶端做很多工作)。 – 2010-06-24 14:52:23

+0

不是,他們可以在IDE中實現帶有存根的接口,這些存根可以返回默認值或拋出異常。如果他們不打算用,我會認爲這個例外是一個適當的方法。你的例子沒有顯示需要什麼接口,什麼接口不是。 – 2010-06-24 14:54:48

+0

如果IStartStop接口不是必需的,正如我在我的答案中提到的那樣,您可以將其從IPreferencesReader界面中刪除 - 除非它需要出於其他原因。 – 2010-06-24 15:07:25

2

我認爲你需要研究爲什麼你不能分解你的界面層次。你說平等是必要的,但有些類不需要實現所有的方法。這意味着,不應該有必要!

如果IPreferencesReader不需要實現M1方法,那麼它確實不是一個IStart。它所做的合同是無效的。

請記住,類可以繼承多個接口。假設你分手的繼承層次結構,那麼如果PreferencesReaderBase確實ISTOP的東西,但不是ISTART的東西,你可以聲明爲:

public class PreferencesReaderBase : IPreferencesReader, IStop 

如果出於某種原因你真的不能分手了這個接口,你可以考慮分解實施類。

class Start 
{ 
    M1() 
    { 

    } 
} 

class Stop 
{ 
    M2() 
    { 

    } 
} 

public class PreferencesReaderBase : IPreferencesReader 
{ 
    private Start start = new Start(); 
    private Stop stop = new Stop() 
    public void M1() 
    { 
     this.start.M1(); 
    } 


    public void M2() 
    { 
     this.stop.M2(); 
    } 
} 

這將至少保持主要的功能類整齊。每個班級都會做一件事,因此Single Responsibility Principle會被維護。

胖接口類然後是一個正義的骨架類,然後可以通過開發迭代大部分保持不變。