带验证的JavaScript链接生成器
在这个Java类中,请注意构造函数是如何被禁止使用的,并被指导实例化和进行验证的接口驱动构建器所取代带验证的JavaScript链接生成器,java,javascript,validation,interface,builder,Java,Javascript,Validation,Interface,Builder,在这个Java类中,请注意构造函数是如何被禁止使用的,并被指导实例化和进行验证的接口驱动构建器所取代 public class Position implements Serializable { private BigDecimal capital; private BigDecimal tolerableRiskInPercentOfCapitalPerTrade; private Direction direction; private BigDecima
public class Position implements Serializable {
private BigDecimal capital;
private BigDecimal tolerableRiskInPercentOfCapitalPerTrade;
private Direction direction;
private BigDecimal pricePerUnit;
private BigDecimal stopLossPricePerUnit;
private Position(){}
public final BigDecimal getTotalTolerableRiskPerTrade() {
return capital.multiply(tolerableRiskInPercentOfCapitalPerTrade.divide(new BigDecimal(100)));
}
public final BigDecimal getStopLossPerUnitLoss() {
if (direction.equals(Direction.LONG)){
return pricePerUnit.subtract(stopLossPricePerUnit);
} else {
return stopLossPricePerUnit.subtract(pricePerUnit);
}
}
public final BigDecimal getStopLossTotalLoss() {
return getStopLossPerUnitLoss().multiply(getUnitsToBuy());
}
public final BigDecimal getUnitsToBuy() {
BigDecimal result = getTotalTolerableRiskPerTrade().divide(getStopLossPerUnitLoss(), 0, BigDecimal.ROUND_DOWN);
if (capital.compareTo(result.multiply(pricePerUnit)) != 1){
return new BigDecimal(0);
} else {
return result;
}
}
public final BigDecimal getTotal() {
return getUnitsToBuy().multiply(pricePerUnit);
}
public static ICapital builder(){
return new Builder();
}
public interface ICapital {
ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital);
}
public interface ITolerableRiskInPercentOfCapitalPerTrade {
IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade);
}
public interface IDirection {
IPricePerUnit direction(final Direction direction);
}
public interface IPricePerUnit {
IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit);
}
public interface IStopLossPricePerUnit {
IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit);
}
public interface IBuild {
Position build();
}
private static class Builder implements ICapital, ITolerableRiskInPercentOfCapitalPerTrade, IDirection, IPricePerUnit, IStopLossPricePerUnit, IBuild {
private final Position instance = new Position();
@Override
public Position build() {
return instance;
}
@Override
public ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital) {
basicValidate(capital);
instance.capital = capital;
return this;
}
@Override
public IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade) {
basicValidate(tolerableRiskInPercentOfCapitalPerTrade);
if (tolerableRiskInPercentOfCapitalPerTrade.compareTo(new BigDecimal(100)) != -1) {
throw new IllegalArgumentException("riskInPercent must be lower than 100");
}
instance.tolerableRiskInPercentOfCapitalPerTrade = tolerableRiskInPercentOfCapitalPerTrade;
return this;
}
@Override
public IPricePerUnit direction(final Direction direction) {
if (direction==null) {
throw new IllegalArgumentException("argument can't be null");
}
instance.direction = direction;
return this;
}
@Override
public IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit) {
basicValidate(pricePerUnit);
instance.pricePerUnit = pricePerUnit;
return this;
}
@Override
public IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit) {
basicValidate(stopLossPricePerUnit);
if (instance.direction.equals(Direction.LONG) && instance.pricePerUnit.compareTo(stopLossPricePerUnit) != 1) {
throw new IllegalArgumentException("price must be higher than stopLossPrice");
}
if (instance.direction.equals(Direction.SHORT) && stopLossPricePerUnit.compareTo(instance.pricePerUnit) != 1) {
throw new IllegalArgumentException("stopLossPrice must be higher than price");
}
instance.stopLossPricePerUnit = stopLossPricePerUnit;
return this;
}
}
protected static void basicValidate(final BigDecimal bigDecimal) {
if (bigDecimal == null) {
throw new IllegalArgumentException("argument can't be null");
}
if (!(bigDecimal.signum() > 0)) {
throw new IllegalArgumentException("argument must have positive signum");
}
}
}
导致像这样的实例化
Position.builder()
.capital(new BigDecimal(10000))
.tolerableRiskInPercentOfCapitalPerTrade(new BigDecimal(2))
.direction(Direction.LONG)
.pricePerUnit(new BigDecimal(25))
.stopLossPricePerUnit(new BigDecimal(24))
.build();
尝试在不同语言之间移植代码并不容易,相同的功能不可能也不应该出现。也就是说,有没有办法在JavaScript中模拟类似的功能?(如有必要,也可以通过一些模块/库)有几种方法可以做到这一点 一种选择是几乎完全相同的方式:使用具有指定细节的方法的生成器对象和调用以获取最终对象的
build
方法(或类似方法)。生成对象的结果调用看起来几乎完全相同(模类型名称等等)
另一个选项是利用JavaScript的对象初始值设定项语法(也称为“对象文字”)来拥有一个“选项”对象,您可以将其传递到位置的构造函数中,如下所示:
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
this.capital = options.capital;
// ...
}
用法:
var p = new Position({
capital: 10000,
tolerableRiskInPercentOfCapitalPerTrade: 2,
direction: Direction.LONG,
pricePerUnit: 25,
stopLossPricePerUnit: 24
});
在构造函数中,如果要将选项中的数据直接用作新实例的属性,可以使用函数top将其复制到:
function applyOptions(instance, options) {
Object.keys(options).forEach(function(key) {
instance[key] = options[key];
});
return instance;
}
然后:
(如果使用jQuery,它有一个基本上可以做到这一点的函数;如果使用下划线,它有和。)
但是,如果要在将选项存储为新实例的属性之前对其进行一些操作,那么像这样的盲拷贝就不太理想了。旁注:我看到您在上面使用了大量的BigDecimal
。JavaScript的本机数字类型使用IEEE-754双精度值(就像Java的double
一样),因此存在double
所具有的精度问题。如果这是一个问题,您将需要为JavaScript找到一个类似于BigDecimal
的库(有几种选择,包括[我没有使用过它,也不能担保,但它已经存在了一段时间])。
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
applyOptions(this, options);
}