重构:用方法对象替换方法解释

Refactoring: Replace Method with Method Object explanation

我正在寻找重构一个太长的方法。搜索我发现了这个技巧:Replace Method with Method Object 但我一点也不明白。

如果重构的方法是:

public class Order {
  //Method to refactor
  public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

     //compute impl
  }

 //.....
}

对于 Web 示例,重构 用方法对象替换方法 将如下所示:

public class Order {

  //Method refactored
  public double price() {
    return new PriceCalculator(this).compute();
  }
  //.......
}

//Method object
public class PriceCalculator {
  private double primaryBasePrice;
  private double secondaryBasePrice;
  private double tertiaryBasePrice;

  public PriceCalculator(Order order) {
    //??
  }

  public double compute() {
    // impl
  }
}

但是 PriceCalculator 如何获取 primaryBasePricesecondaryBasePricetertiaryBasePrice 值来进行计算?

我只看到可以在构造函数中传递值,如下所示:

//Method object
public class PriceCalculator {
  private double primaryBasePrice;
  private double secondaryBasePrice;
  private double tertiaryBasePrice;

  public PriceCalculator(Order order, double primaryBasePrice, 
     double secondaryBasePrice, double tertiaryBasePrice) {
    this.primaryBasePrice = primaryBasePrice;
    this.secondaryBasePrice = secondaryBasePrice;
    this.tertiaryBasePrice = tertiaryBasePrice;
  }

  public double compute() {
    // impl
  }
}

不然为什么要在构造函数中传入order实例引用呢?为什么需要?

但是 PriceCalculator 如何获取 primaryBasePrice、secondaryBasePrice、tertiaryBasePrice 值来进行计算?

和重构前一样。

如果你看原始代码,primaryBasePricesecondaryBasePricetertiaryBasePrice本地变量,其值在某处设置在 //compute impl 部分。

  public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

     // compute impl
     // all base price variables are assigned somewhere in here
  }

重构后,compute() 方法具有 //compute impl 代码的副本,并简单地将完全相同的值分配给 PriceCalculator 中的字段,就像它对局部变量所做的那样重构之前。

我们需要传递对 Order 对象的引用,以防这些值取决于其方法或内部状态。

例如,如果我们之前有

public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

    // some of compute impl
    primaryBasePrice = getPrimary();
    secondaryBasePrice = getSecondary();
    tertiaryBasePrice = getTertiary();
    // the rest of compute impl
}

重构后,我们会变成类似

的东西
public double compute() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;

    // some of compute impl
    primaryBasePrice = order.getPrimary();
    secondaryBasePrice = order.getSecondary();
    tertiaryBasePrice = order.getTertiary();
    // the rest of compute impl
}

所以回答你的两个问题:

  1. But how PriceCalculator gets primaryBasePrice, secondaryBasePrice, tertiaryBasePrice values to do the compute?

。是的,你是对的,你需要将它们作为构造函数参数发送。

  1. Otherwise, why pass in the constructor order instance reference? Why is needed?

您需要传递订单实例引用才能调用订单的其他方法。在你给出的例子中,它是一个简单的方法,但在其他一些方法中你可能会调用订单的一些方法......

这种重构技术的一个问题是,如果您的原始方法访问 Order 的私有方法,那么您必须使它们受到包保护或在目标方法对象中复制这些方法...

如果你将这些私有方法作为包保护,那么你会得到紧耦合、功能嫉​​妒和其他问题