设计问题 - 继承是简化此代码的正确方法吗?

时间:2010-08-23 20:37:54

标签: c# design-patterns inheritance

我有一个我想解决的设计问题。 我有一个接口,我们称之为IProtocol,它由两个独立的类实现。我们在这里查看600多行代码。他们所做的绝大多数事情是相同的,以外的某些特定领域,例如DiffStuff();

目前的结构是这样的:

public class Protocol1 : IProtocol
{
  MyInterfaceMethod1()
  {
     Same1();
     DiffStuff();
     Same2();
  }
}

public class Protocol2 : IProtocol
{
  MyInterfaceMethod1()
  {
     Same1();
     Same2();
  }
}

如果我将两个协议分开,我担心会出现复制粘贴错误和代码重复的典型问题。我们讨论的是每行600行代码,而不是一些简单的方法。

我正在考虑将Protocol1的实现更改为从protocol2继承,就像这样(Protocol2基本上保持不变,除了我必须将Same1()Same2()包装到私有方法中。)

public class Protocol1 : Protocol2
{
  void Same1()
  {
     base.Same1();
  }

  void Same2()
  {
     base.Same2();
  }

  MyInterfaceMethod1()
  {
     Same1();
     DiffStuff();
     Same2();
  }
}  

这是处理这个问题的正确方法吗?

修改 很多人帮助我解决了这个问题,感谢他们的明确理解。在我的例子中,两个对象的类型不同,即使它们的大部分实现都是共享的,所以我使用Bobby's suggestion来使用抽象基类,创建小方法来封装类之间的更改。另外感谢:

  • jloubert
  • Hans Passant
  • Jeff Sternal

6 个答案:

答案 0 :(得分:7)

    /// <summary>
    /// IProtocol interface
    /// </summary>
    public interface IProtocol
    {
        void MyInterfaceMethod1();
        void Same1();
        void Same2();
    }

...然后

public abstract class ProtocolBase : IProtocol
{
    #region IProtocol Members

    public void MyInterfaceMethod1()
    {
        // Implementation elided...
    }

    public void Same1()
    {
        // Implementation elided...
    }

    public void Same2()
    {
        // Implementation elided...
    }

    public abstract void DiffStuff();

    #endregion
}

最后...

public sealed class Protocol1 : ProtocolBase
{
    public override void DiffStuff()
    {
        // Implementation elided...
    }
}

public sealed class Protocol2 : ProtocolBase
{
    public override void DiffStuff()
    {
        // Implementation elided...
    }
}

答案 1 :(得分:5)

不完全。添加Same1和Same2方法没有意义,您可以从ProtocolBase继承它们。并且DiffStuff()应该是一个虚方法,以便您可以覆盖它并赋予它不同的行为。

答案 2 :(得分:4)

你非常接近于描述template method pattern,它有很长的血统作为解决像你这样的问题的有效解决方案。

但是,您应该考虑使用合成而不是继承。 The two approaches offer different advantages and disadvantages,但组成通常(通常是?)更好 *

 public class Protocol {

      private ISpecialHandler specialHandler;

      public Protocol() {}

      public Protocol(ISpecialHandler specialHandler) {
          this.specialHandler = specialHandler;
      }

      void Same1() {}
      void Same2() {}

      public void DoStuff() {
          this.Same1();
          if (this.specialHandler != null) {
              this.specialHandler.DoStuff();
          }
          this.Same2();
      }
 }

然后,调用者可以传入提供专门算法的对象实例(strategies)来处理手头的任何情况:

 Protocol protocol1 = new Protocol(new DiffStuffHandler());
 protocol1.DoStuff();

* 请参阅Patterns I Hate #2: Template Method,详细解释为什么在您的情况下,合成通常优于继承。

答案 3 :(得分:0)

我更好的设计(在我看来)

public abstract class Protocol_common : IProtocol 
{ 
  MyInterfaceMethod1() 
  { 
     Same1(); 
     DiffStuff(); 
     Same2(); 
  } 

  abstract void DiffStuff();

}

public class Protocol1 : Protocol_common
{ 
  DiffStuff() 
  { 
      /// stuff here.
  } 
}

public class Protocol2 : Protocol_common
{ 
  DiffStuff() 
  { 
      /// nothing here.
  } 
}

(这实际上比正确的C#更多的伪代码,但我达到了高点)

答案 4 :(得分:0)

您可能想要考虑这种类型的模式是否有效:

public class ProtocolHelper
{
    public void Same1() {}
    public void Same2() {}
}

public class Protocol1 : IProtocol
{
    private readonly ProtocolHelper _helper = new ProtocolHelper();

    void MyInterfaceMethod1()
    {
        _helper.Same1();
        DiffStuff();
        _helper.Same2();
    }
}

您可以通过查看是否可以为“ProtocolHelper”类找到一个好名字来判断这是否有意义。如果一个名字自然来自你的逻辑,那么这是打破课程的好方法。您可能需要将一些依赖项(例如私有字段)作为参数传递给方法,以使其工作。

答案 5 :(得分:-1)

我同意MathEpic。我会使用Template method模式。