我正在使用Builder模式来更轻松地创建对象。但是,标准构建器模式示例不包括我的代码中需要的错误检查。例如,accessibility
对象中的demandMean
和Simulator
数组应具有相同的长度。代码的简要框架如下所示:
public class Simulator {
double[] accessibility;
double[] demandMean;
// Constructor obmitted for brevity
public static class Builder {
private double[] _accessibility;
private double[] _demandMean;
public Builder accessibility(double[] accessibility) {
_accessibility = accessiblity.clone();
return this;
}
public Builder demandMean(double[] demandMean) {
_demandMean = demandMean.clone();
return this;
}
// build() method obmitted for brevity
}
}
作为另一示例,在促销优化问题中,存在各种促销车辆(例如传单,显示器)和促销模式,其是一组促销车辆(例如,没有,仅传单,仅显示,传单和显示)。当我创建Problem
时,我必须定义可用的车辆组,并检查促销模式是否使用这些车辆的子集而不是其他一些不可用的车辆,以及促销模式不相同(例如,没有两个促销模式都是“仅传单”)。代码的简要框架如下所示:
public class Problem {
Set<Vehicle> vehicles;
Set<PromoMode> promoModes;
public static class Builder {
Set<Vehicle> _vehicles;
Set<PromoMode> _promoModes;
}
}
public class PromoMode {
Set<Vehicle> vehiclesUsed;
}
我的问题如下:
build()
方法时,是否应在构造函数或构建器中完成错误检查? 答案 0 :(得分:2)
如果在创建对象时需要保持不变量,则在任何参数违反不变量时停止构造。这也是一种快速失败的方法 当您拥有大量参数时,构建器模式有助于创建对象 这并不意味着你不做错误检查 只要参数违反了对象不变量
,就抛出适当的RuntimeException
答案 1 :(得分:1)
您应该使用构造函数,因为这更符合单一责任原则。构建器不负责检查不变量。唯一真正的工作是收集构建对象所需的数据 此外,如果您决定稍后更改该类以使用公共构造函数,则不必移动该代码。
你绝对不应该在setter方法中检查不变量。这有几个好处:
*您只需要检查ONCE
*在诸如代码之类的情况下,由于您在不同时间添加了两个数组,因此无法提前检查不变量。您不知道用户将添加它们的顺序,因此您不知道哪个方法应该运行检查。
除非你的构建器中的setter做了一些强烈的计算(很少是这种情况 - 通常,如果需要进行某种计算,它应该在构造函数中发生),对于'早期失败'没有多大帮助'in,特别是因为像你这样流畅的构建者只使用一行代码来构建对象,所以任何try块都会围绕整行。
答案 2 :(得分:0)
“正确”的方法实际上取决于情况 - 如果构造具有不同大小的数组无效,我会说在构造中进行处理更好,越早捕获无效状态越好。
现在,如果您可以更改阵列并放入不同的阵列 - 那么在调用它们时可能会更好。