更改遗留代码中的不可变类



我想替换(可变(类

class OldValue {
private int value;

public OldValue(int value) { this.value = value; }

public int getValue() { return value; }

public void setValue(int value) { this.value = value; }
}

具有不可变类

class NewValue {
private final int value;

public NewValue(int value) { this.value = value; }

public int getValue() { return value; }

/* no setter, obviously */
}

在代码的大多数部分中,类似于newValue.set(777)的内容可以被newValue = new NewValue(777)替换。然而,代码中有一些遗留部分与类似

class ManagementServiceProviderFacadeSingletonAbstractFactoryObserver {
public void setTheValue(OldValue oldValue) {
oldValue.setValue(555);
}
}
class Data {
private OldValue oldValue;

public OldValue get() { return oldValue; }
}

class SomewhereElse {
public void frobnicate(Data data, ManagementServiceProviderFacadeSingletonAbstractFactoryObserver x) {
x.setTheValue(data.get());
}
}

这些遗留部分很难改变,我们希望尽可能少地进行调整。有没有一种方法可以写一些";邪恶;可以在遗留代码中使用的setter方法?类似的东西

class EvilSetter {
public static void evilSet(NewValue newValue, int x) {
// temporarily make newValue.value both public and non-final, set it to x
}
}

在不失去新设计的永恒性和优雅性的情况下,还有其他方法吗?

我可能会保留这两种类型,让遗留代码单独使用旧类型,并提供适配器方法在两者之间进行转换。

public class LegacyValueAdapter {
public static OldValue toOldValue(NewValue newValue) {
return new OldValue(newValue.getValue);
}
public static NewValue toNewValue (OldValue oldValue) {
return new NewValue(oldValue.getValue);
}
}

清楚地记录这些应该只用于与遗留代码接口,根据需要标记为弃用。这显然并不理想,但这适用于整个情况。

如果类更复杂(例如,也有一些具有非平凡行为的方法(,那么通过包装NewValue的实例来实现OldValue可能是值得的,但在这种简单的情况下,这不会带来太多好处。


我强烈建议不要使用任何反射黑客,因为它们会首先使使用不可变类型的大多数好处失效。不要给我一个看起来不可变的类型,但却以某种方式偷偷地改变了值——这打破了用户的期望,并隐藏了种族条件的风险。

最新更新