C# 更干净的抽象方式

C# 更干净的抽象方式,c#,interface,refactoring,C#,Interface,Refactoring,我正在重构一些旧代码,并对一个设计决策感到震惊 AbstractClassA -Step 1 -Step 2 --Step 2.1 --Step 2.2 -Step 3 上面的抽象类有步骤1、步骤2和步骤3的抽象方法。步骤2始终需要调用方法2.1和2.2。但是在当前的设计中,步骤2.1和2.2并没有声明为抽象的,而是在每个继承类中实现和调用的。我计划通过将所有这些方法(包括2.1和2.2)拉入一个接口来重构代码。然后我计划实现这个接口的抽象类,在这个接口中,步骤2将调用2.1和2.2。但不知怎

我正在重构一些旧代码,并对一个设计决策感到震惊

AbstractClassA
-Step 1
-Step 2
--Step 2.1
--Step 2.2
-Step 3
上面的抽象类有步骤1、步骤2和步骤3的抽象方法。步骤2始终需要调用方法2.1和2.2。但是在当前的设计中,步骤2.1和2.2并没有声明为抽象的,而是在每个继承类中实现和调用的。我计划通过将所有这些方法(包括2.1和2.2)拉入一个接口来重构代码。然后我计划实现这个接口的抽象类,在这个接口中,步骤2将调用2.1和2.2。但不知怎么的,这看起来并不整洁。我想知道这个设计是否有缺陷

InterfaceA
-Step1
-Step2
-Step 2.1
-Step 2.2
-Step3

您必须问自己,子类中步骤2.1和步骤2.2的实现是否是专门化的,也就是说,每个子类实现自己的步骤是否有意义。如果是这样,那么就把它们抽象化。如果没有,请使用通用实现,甚至不要将其虚拟化。如果你这样做,它甚至可能很整洁。

那么,你需要界面吗,还是你认为你需要


我听说你有AbstractClassA,它有两个被另一个方法调用的方法。如果这两个方法应该是可公开访问的,那么将它们放入接口中。如果不是,则不要这样做,而是在接口的抽象实现中使它们成为受保护的虚拟或受保护的抽象。

因此,似乎Step2是接口的一部分—此类的调用者希望能够调用Step2。但是Step2.1和Step2.2是一个实现细节,这是你不希望调用方看到的,尽管接口的所有实现者都会以这种方式实现——我说得对吗

如果是这样的话,那么我会让接口包括Step1、Step2和Step3(仅限)。抽象类将实现Step2,并进一步定义受保护的Step2.1和Step2.2,但将它们定义为抽象类,从而强制子类提供实现


除非您的意思是Step2.1和Step2.2在所有子类中都是相同的,否则我会将它们设置为私有的,并将它们放在抽象类中。

听起来您想要的是:

interface IMyInterface
{
    void Step1();
    void Step2();
    void Step3();
}

abstract class MyBaseClass : IMyInterface
{
    public abstract void Step1();
    public void Step2()
    {
        Step2_1();
        Step2_2();
    }
    public abstract void Step3();

    protected abstract void Step2_1();
    protected abstract void Step2_2();
}

当您希望泛指运行时将要使用的确切实例可以更改的某个对象时,请使用接口进行抽象。使用一个基类来实现共享,这样您就可以在每个子类中定义步骤2.1和步骤2.2中发生的事情,但是您的基类定义步骤2意味着执行步骤2.1,然后执行步骤2.2。

步骤2.1和步骤2.2做什么?Eric:这有关系吗?我想很接近,但是
公共虚拟空间步骤2()
似乎很合适,因为Step2()可以被子类重写。这是有意的,因为如果您允许重写Step2,那么每个子类的编写者都必须知道始终调用Step2.1和Step2.2,这(不知道您的确切情况)似乎会破坏设计的清洁度。您是否可以将可能从一个实现更改为另一个实现的部分分离为单独的虚拟方法(例如步骤2.0),但将接口方法保留为非虚拟方法,并让它调用步骤2.0、步骤2.1、步骤2.2?