如何提取抽象?

时间:2013-04-17 07:47:51

标签: oop design-patterns

我的问题很简单,但我找不到合适的解决方案。

代码(仅举例):

public class ToRefact
{
    public int Func1(int i)
    {
        int a = i;
        a++;
        a++;
        a++;

        int b = FuncX2(a); //b = a * 2;

        b++;
        b++;
        b++;
        return a + b;
    }

    public int Func2(int i)
    {
        int a = i;
        a++;
        a++;
        a++;

        int b = FuncX3(a); // b = a * 3;

        b++;
        b++;
        b++;
        return a + b;
    }

    private int FuncX2(int b)
    {
        return b * 2;
    }

    private int FuncX3(int b)
    {
        return b * 3;
    }
}

我们可以看到,func1和func2具有相同的主体,除了代码中间:差异是FuncX2和FuncX3。但是,我不能做基础抽象类,因为这个代码在中间! 我怎样才能做普通的抽象?请不要改变操作(3次++,3次b ++)并且不要改变序列

谢谢

5 个答案:

答案 0 :(得分:2)

假设您选择的语言可以传递给函数的“指针”:

public class ToRefact
{
    private int Func(int i, Func<int, int> f)
    {
        int a = i;
        a++;
        a++;
        a++;

        int b = f(a); //b = a * 2;

        b++;
        b++;
        b++;
        return a + b;    
    }

    public int Func1(int i)
    {
        return Func(i, FuncX2);
    }

    public int Func2(int i)
    {
        return Func(i, FuncX3);
    }

    private int FuncX2(int b)
    {
        return b * 2;
    }

    private int FuncX3(int b)
    {
        return b * 3;
    }
}

答案 1 :(得分:1)

或者,您可以创建更模块化和可测试的方法。

创建ICalculator界面,如:

 public interface ICalculator
 {
      int Calculate(int a);
 }

两个具体实现

public class CalculatorX : ICalculator
{
      public int Calculate(int a)
      {
          return a * 2;
      }
}

public class CalculatorY : ICalculator
{
      public int Calculate(int a)
      {
          return a * 3;
      }
}

然后你会接受这个作为参数:

public int Func1(ICalculator calculator)
{
    int a = i;
    a++;
    a++;
    a++;

    int b = calculator(a); 

    b++;
    b++;
    b++;
    return a + b;
}

并称之为:

var calculatorX = new CalculatorX();
var result = Func1(calculatorX );

这样可以轻松替换实现,模拟它们,甚至使用您喜欢的IoC容器注入它们。您还明确指定了方法的契约,因此,如果您必须添加新的实现,则可以通过界面了解要实现的内容。

答案 2 :(得分:1)

您可以使用template method(甚至strategy pattern,具体取决于实际情况)但在这个简单的情况下,我会做这样的事情:

public class ToRefact
{
    public int Func1(int i)
    {
        int a = FuncAdd3(i);

        int b = FuncX2(a); //b = a * 2;

        b = FuncAdd3(b);
        return a + b; // Or more compact FuncAdd3(i) + FuncAdd3(FuncX2(FuncAdd3(i)))
    }

    public int Func2(int i)
    {
        int a = FuncAdd3(i);

        int b = FuncX3(a); //b = a * 2;

        b = FuncAdd3(b);
        return a + b; // Or more compact FuncAdd3(i) + FuncAdd3(FuncX3(FuncAdd3(i)))
    }

    private int FuncAdd3(int b)
    {
        return b + 2;
    }

    private int FuncX2(int b)
    {
        return b * 2;
    }

    private int FuncX3(int b)
    {
        return b * 3;
    }
}

答案 3 :(得分:0)

public class ToRefact{
    public int Func1(int i){
        int a = i;
        a = addThree(a);

        int b = FuncX2(a); //b = a * 2;

        b = addThree(b);
        return a + b;
    }

    public int Func2(int i){
        int a = i;
        a = addThree(a);

        int b = FuncX3(a); // b = a * 3;

        b = addThree(b);
        return a + b;
    }

    private int FuncX2(int b){
        return b * 2;
    }

    private int FuncX3(int b){
        return b * 3;
    }

    private int addThree(int x){
        x++;
        x++;
        x++;
        return x;
    }
}

答案 4 :(得分:0)

您可以创建基类并应用template method设计模式。

示例

请注意,我使用Delphi是最容易从内存中编写的,但每种语言中的意图都是相同的

  TCustomRefact = class(TObject)
  protected
    function Calculate;
    function Multiply(const Value: Integer); virtual; abstract;
  end;

  TRefact1 = class(TCustomRefact )
  protected
    function Multiply(const Value: Integer); override;
  end;

  TRefact2 = class(TCustomRefact )
  protected
    function Multiply(const Value: Integer); override;
  end;