Пропуск лишней проверки с неизменными маховиками
У меня есть неизменный класс, который выглядит примерно так:
final class Foo {
private final String name;
private final MutableObject mo;
public Foo(String name, MutableObject mo) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo);
}
}
bar
метод возвращает Foo
объект, смешивая внутренности двух существующих Foo
объекты. Поскольку MutableObject
уже в Foo
объект, он гарантированно действителен и не требует копирования или проверки (что в настоящее время делает конструктор).
Поскольку проверка (и, возможно, клон?) Стоят дорого, я бы хотел их избежать, если это возможно. Какой лучший способ сделать это? Это было то, что я придумал:
final class Foo {
private final String name;
private final MutableObject mo;
public Foo(String name, MutableObject mo) {
this(name, mo, VerificationStyle.STRICT);
}
private Foo(String name, MutableObject mo, VerificationStyle vs) {
if(vs == VerificationStyle.STRICT) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
}
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo, VerificationStyle.LENIENT);
}
private static enum VerificationStyle { STRICT, LENIENT; }
}
Я думал, что, по крайней мере, это будет чище / яснее, чем использование фиктивного параметра, и менее подвержен ошибкам, чем подмена порядка, но есть ли лучший способ сделать это? Как это обычно достигается?
1 ответ
Может быть, полностью скрыть конструктор и создать новые экземпляры, используя метод, подобный фабрике, например:
private Foo(String name, MutableObject mo) {
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo);
}
public static Foo create(String name, MutableObject mo) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
return new Foo(name, mo);
}