如何重构胖接口?

时间:2010-06-24 14:14:22

标签: c# design-patterns refactoring interface

假设我有以下一组接口......

 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,我的类将如下所示。这是一个胖接口的例子,其中i 将不得不提供我可能不需要的所有方法的实现。

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();
        }
    }

我可以为这种情况应用任何模式以便重构吗?

编辑:我不能没有这种层次结构,因为无法删除任何接口。

感谢您的关注。

3 个答案:

答案 0 :(得分:2)

您不一定需要提供有效的实施方案。在您的示例中,您的IPreferencesReader看起来不需要IStartStop,那么您可以简单地删除它吗?

如果要隐藏实现类型的接口方法(即,您不会在PreferencesReaderBase对象上看到它),您可以实现接口明确:

void IStart.Start() { }

然后,您只能通过将PreferencesReaderBase引用转换为IStart引用来调用这些接口方法。

答案 1 :(得分:2)

我认为你需要研究为什么你不能分解你的界面heirarchy。你说heirarchy是必要的,但有些类不需要实现所有的方法。这意味着不需要层次化!

如果IPreferencesReader不需要实现M1方法,那么它确实不是IStart。它正在签订的合同是无效的。

请记住,类可以继承多个接口。假设你打破了继承heirarchy,那么如果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得以维持。

胖接口类是一个公正的骨架类,然后可以在开发迭代中保持不变。

答案 2 :(得分:1)

使用“适配器”模式 - 而不是维基百科标识的one,所以也许我的术语是非标准的 - 但是像Java的MouseAdapter

  

一个抽象适配器类   接收鼠标事件。方法中   这个班是空的。这个班   存在是为了创造的便利   听众对象。

     

...

     

扩展此类以创建一个   MouseEvent监听器并覆盖   感兴趣的事件的方法。   (如果实现MouseListener   界面,你必须定义所有   其中的方法。这个抽象类   为它们定义所有的null方法,所以   你只能定义方法   对于你关心的事件。)

只需编写一个抽象类,它包含所有必要接口的空实现;将其子类化并覆盖与您的需求相关的方法。

全脂界面仍然存在;它仍然由你的类实现(通过继承) - 但是你的类的代码只包含重要的内容。