2010-06-24 81 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会被维护。

胖接口类然后是一个正义的骨架类,然后可以通过开发迭代大部分保持不变。