java - 更改遗留代码中的不可变类
问题描述
我想替换(可变)类
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());
}
}
这些遗留部分很难更改,我们希望尽可能少地对其进行调整。有没有办法编写可以在遗留代码中使用的某种“邪恶”设置方法?就像是
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);
}
}
清楚地记录这些应该仅用于与遗留代码的接口,根据需要标记为已弃用。这显然并不理想,但这适用于整个情况。
如果类更复杂(例如,也有一些非平凡行为的方法),可能值得OldValue
通过包装 的实例来实现NewValue
,但在这种简单的情况下不会提供太多好处。
我强烈建议不要使用任何反射黑客,因为它们首先会使使用不可变类型的大部分好处无效。不要给我一个看起来不可变的类型,然后以某种方式偷偷改变值 - 这打破了用户的期望并隐藏了竞争条件的风险。
推荐阅读
- mysql - 加入表和字符串比较(大型数据集)
- wix - 如何防止 Wix 安装旧版本?
- arrays - Angular 2 如何使用 Ng For 将索引连接到对象及其数组中
- bash - 进程替换和退出代码
- mongodb - 地理空间搜索返回的结果少于可用的结果
- r - 如何指示 R 将 ggplot 保存在执行脚本的同一目录中?
- xml - 将 XML 文件附加到现有的 Access 表
- c# - ValidateCredentials() - 安全问题
- python - Python 2.7 将编码的文本文件读取为代码而不是文本。(用 io 模块修复)
- python - Pandas Dataframe 中的行列表列表