我是否违反了 "open/closed" 原则?
Am I violating the "open/closed" principle?
场景:我在 class 字段中存储了一些信息(例如双精度数组)(比如字段 Measurements
,class MeasureData
中的整数数组).现在我想使用这些数据来执行一些计算(例如计算数组的算术平均值、最大值和最小值)。目前,我不知道将来是否需要对这些数据进行任何其他操作(例如,也许我需要获取标准偏差、总和或其他)。我会有很多 MeasureData
.
类型的对象
解决方案:我可以写一个 class Calculator
,将其声明为最终的,使用私有构造函数并使用几个静态方法来执行我需要的计算。这似乎是有道理的,因为 Calculator
充当实用程序 class,没有任何字段,很像标准 Math
class.
问题:如果几个月后我需要进行任何其他计算,我将需要在 Calculator
中编写另一个静态方法。这是否意味着违反open/closed原则(毕竟我是在修改classCalculator
的实现)?
严格的回答是肯定的; OCP 声明 class 对扩展开放但对修改关闭。您将修改 Calculator
,并因此违反 OCP(正如您已经得出的结论)。
这导致两点:
首先,在这种情况下违反 OCP 有什么大不了的吗?您正在附加地更改 Calculator
以向其添加新方法。 Calculator
是一个静态助手 class,用于从您的对象中获取有意义的数据。添加新方法,如计算 SD,不会影响其中的任何其他操作。如果 正确实施 ,添加此方法真的会危及您的项目吗?
其次,如果您觉得违反 OCP 的行为是不可接受的,那么这是教科书示例,其中可以利用 Strategy Pattern。考虑:
Measurements.Java
public class Measurements {
private int[] data;
public Measurements(int[] data) {
this.data = data;
}
public Number performCalculation(Calculation c) {
return c.performCalculation(data);
}
}
Calculation.java
public interface Calculation {
Number performCalculation(int[] data);
}
然后您可以为要对数据执行的每个不同计算进行计算 class(例如:MeanCalculation
、StdDevCalculation
等)。如果您想要一个新的计算(例如:MedianCalculation
),您可以在不修改该区域中的任何其他代码的情况下进行计算(关闭修改,打开扩展;OCP 兼容)。最终结果如下:
Measurements values = ...
Number mean = values.performCalculation(new MeanCalculation());
Number SD = values.performCalculation(new StdDevCalculation());
// etc.
我并不是说这是针对您的具体情况的最佳方法(甚至是该方法的最佳实施);你需要自己回答这个问题。但我希望这个答案能为这个问题提供一个体面的外部视角。
场景:我在 class 字段中存储了一些信息(例如双精度数组)(比如字段 Measurements
,class MeasureData
中的整数数组).现在我想使用这些数据来执行一些计算(例如计算数组的算术平均值、最大值和最小值)。目前,我不知道将来是否需要对这些数据进行任何其他操作(例如,也许我需要获取标准偏差、总和或其他)。我会有很多 MeasureData
.
解决方案:我可以写一个 class Calculator
,将其声明为最终的,使用私有构造函数并使用几个静态方法来执行我需要的计算。这似乎是有道理的,因为 Calculator
充当实用程序 class,没有任何字段,很像标准 Math
class.
问题:如果几个月后我需要进行任何其他计算,我将需要在 Calculator
中编写另一个静态方法。这是否意味着违反open/closed原则(毕竟我是在修改classCalculator
的实现)?
严格的回答是肯定的; OCP 声明 class 对扩展开放但对修改关闭。您将修改 Calculator
,并因此违反 OCP(正如您已经得出的结论)。
这导致两点:
首先,在这种情况下违反 OCP 有什么大不了的吗?您正在附加地更改 Calculator
以向其添加新方法。 Calculator
是一个静态助手 class,用于从您的对象中获取有意义的数据。添加新方法,如计算 SD,不会影响其中的任何其他操作。如果 正确实施 ,添加此方法真的会危及您的项目吗?
其次,如果您觉得违反 OCP 的行为是不可接受的,那么这是教科书示例,其中可以利用 Strategy Pattern。考虑:
Measurements.Java
public class Measurements {
private int[] data;
public Measurements(int[] data) {
this.data = data;
}
public Number performCalculation(Calculation c) {
return c.performCalculation(data);
}
}
Calculation.java
public interface Calculation {
Number performCalculation(int[] data);
}
然后您可以为要对数据执行的每个不同计算进行计算 class(例如:MeanCalculation
、StdDevCalculation
等)。如果您想要一个新的计算(例如:MedianCalculation
),您可以在不修改该区域中的任何其他代码的情况下进行计算(关闭修改,打开扩展;OCP 兼容)。最终结果如下:
Measurements values = ...
Number mean = values.performCalculation(new MeanCalculation());
Number SD = values.performCalculation(new StdDevCalculation());
// etc.
我并不是说这是针对您的具体情况的最佳方法(甚至是该方法的最佳实施);你需要自己回答这个问题。但我希望这个答案能为这个问题提供一个体面的外部视角。