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

本文关键字:方法 解释 替换 对象 重构 | 更新日期: 2023-09-27 18:06:07

我正在寻找重构一个太长的方法。搜索我发现了这个技术:用方法对象替换方法,但我完全不理解。

如果重构的方法是:

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如何得到primaryBasePrice, secondaryBasePrice, tertiaryBasePrice的值来进行计算呢?

我只看到可以将构造函数中的值作为next传递:

//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实例引用?为什么需要?

  • order的传递实例:

    return new PriceCalculator(this, primaryBasePrice, secondaryBasePrice, tertiaryBasePrice).compute();

  • 没有order实例引用:

    return new PriceCalculator(primaryBasePrice, secondaryBasePrice, tertiaryBasePrice).compute();

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

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

和重构前一样。

如果您查看原始代码,primaryBasePrice, secondaryBasePricetertiaryBasePrice本地变量,其值在//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. 但是PriceCalculator如何获取primaryBasePrice, secondaryBasePrice,terarybaseprice值做计算?

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

  • 否则,为什么传入构造函数顺序实例引用?为什么是必要的吗?

  • 您需要传递order实例引用,以便能够调用order的其他方法。在您给出的示例中,这是一个微不足道的方法,但在其他一些方法中,您可能会调用Order的一些方法…

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

    如果你将这些私有方法设置为包保护,那么你就会遇到紧耦合,功能嫉妒和其他问题