Java 设计决策:向方法添加新参数V/S创建实例变量

Java 设计决策:向方法添加新参数V/S创建实例变量,java,oop,Java,Oop,假设我们有一个类Shape,它有一个方法rotate(int-velocity)。此方法使形状以速度(传递给旋转的参数)旋转。这个方法已经在一个项目中被调用过,比如说在100个地方 但现在出现了一个新的要求,即旋转功能也将取决于形状的颜色,即如果颜色为蓝色,则速度应降低1,否则不应进行任何更改 此问题的一个解决方案是将rotate(int-velocity)方法更改为rotate(int-velocity,Color-Color),然后在rotate方法中添加if语句以检查颜色,并在rotat

假设我们有一个类Shape,它有一个方法rotate(int-velocity)。此方法使形状以速度(传递给旋转的参数)旋转。这个方法已经在一个项目中被调用过,比如说在100个地方

但现在出现了一个新的要求,即旋转功能也将取决于形状的颜色,即如果颜色为蓝色,则速度应降低1,否则不应进行任何更改

  • 此问题的一个解决方案是将rotate(int-velocity)方法更改为rotate(int-velocity,Color-Color),然后在rotate方法中添加if语句以检查颜色,并在rotate的100个调用中进行更改。 例如

    shape.rotate(50,蓝色)

在旋转方法中

void rotate(int velocity, Color color) {
  if(color == blue)
      --velocity ;
}
void rotate(int velocity) {
  if(this.color == blue)
    --velocity ;
}
  • 另一种解决方案是将颜色作为shape对象的实例变量,然后在不向rotate方法添加新参数的情况下,只需在调用之前设置颜色,并在rotate方法内挤压if检查。 例如

    在旋转方法中

    void rotate(int velocity, Color color) {
      if(color == blue)
          --velocity ;
    }
    
    void rotate(int velocity) {
      if(this.color == blue)
        --velocity ;
    }
    
  • 另一个解决方案是重载rotate方法,创建一个名为rotate(int-velocity,Color-Color)的新方法,并在新调用中使用它。这将使使用旋转(int-velocity)的现有代码保持不变

以下哪一种可能是最好的解决方案或者,是否存在更好的解决方案?如果是,那么可能是什么


问候

我想说,你需要问自己几个问题

  • 您是否关心
    rotate
    方法外部的颜色?如果是,则将其作为实例变量;如果否,则将其传递给rotate方法

  • 您可能会在意
    rotate
    方法后面的颜色吗?如果是,则将其作为实例变量;如果否,则将其传递给rotate方法

  • 调用rotate方法时,您是否总是关心颜色?如果是,则将其作为参数(强制他们在旋转形状时设置颜色)

  • 我认为第一个选项的实现非常繁琐。如果你错过了一个地方,如果以后你意识到你需要再次旋转(单参数),该怎么办
  • 正如许多人已经指出的那样,第二种选择是不相关的
  • 第三,我认为这是最好的解决方案,因为它不会破坏你的代码。您可以使用这两种重载方法,也可以根据需要使用其中任何一种
    至于我,我在这里看到了继承用法的经典示例

    class Shape {
      public void rotate(int v) {}
    }
    
    class GreenShape extends Shape {
      public void rotate(int v){
        super.rotate(v + 10);
      }
    }
    

    OO的一个好原则是将相关的行为和状态放在一起。在这种情况下,形状的旋转行为取决于形状的颜色状态,因此将两者放在形状类c.q中是有意义的。创建一个字段“color”,并在旋转方法中使用它来自定义旋转行为

    除了这个设计决策之外,您还真的在问一个重构决策:如何处理依赖于形状的应用程序代码?在这种情况下,我的方法是提前思考:我们可以预期Shape类会有多少这样的变化?如果这是一个罕见的更改,那么您可以继续更改初始化shape类的所有代码位置,以便设置颜色。如果形状更频繁地改变,那么您应该更加严格,并减少代码之间的紧密耦合。在这种情况下,一种方法是创建一个抽象工厂(或者使用像Spring这样的D.I.框架提供的工厂),这样应用程序代码就不需要知道形状的创建细节


    顺便说一句,您的第三个选项对我来说似乎是次优的:部分代码没有意识到在形状中添加了颜色状态,并且一直调用旧的“不推荐的”旋转方法。这意味着,将形状的颜色设置为蓝色不会普遍影响旋转行为,但仅在“特殊情况”下。这削弱了设计,使开发人员在理解它之后更难理解它。

    如果你的新属性真的是对象的属性(就像颜色IMHO代表形状),那么它不应该是
    rotate()
    的参数,而应该是具有自己的getter和setter的对象属性。好吧,但是如果颜色是一个实例变量,如果有人在调用rotate(50)之前没有调用setColor(blue),该怎么办?这取决于域语义:拥有无色对象可以吗?也许有默认的颜色?等等。如果使用无色对象不合适,那么应尽早抛出InvalidStateException。我认为你是对的,但这给我带来了新的问题:参考第3点。对于您的答案,是否最好创建一个新的重载方法
    rotate(int-velocity,Color)
    ,以便不必更改使用现有
    rotate(int-velocity)
    方法的代码。此外,在这种情况下,可能有一些透明对象(例如,在现有代码中)没有任何颜色,并且到目前为止一直在使用
    rotate(int-velocity)
    方法。如果我们将另一个参数添加到
    rotate
    ,这些调用必须传入
    null
    作为color参数的参数。@vaibhav这肯定是问题3的“否”答案吗?如果你并不总是关心颜色,那么你就不想强迫他们指定一种颜色,而使用两种旋转方法是最好的选择。颜色是形状的一种属性。一旦决定添加它,在旧的rotate方法中默认忽略它有点误导。您可以在JavaDoc中指定,如果没有显式设置,则将使用特定的默认颜色。从OO的角度来看,这似乎是一个糟糕的设计选择(避免straig)