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

q7solyqu  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(230)

我想替换(可变)类

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
  }
}

有没有别的办法不失去新设计的不变性和优雅?

wvyml7n5

wvyml7n51#

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

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 通过 Package NewValue ,但在这个简单的例子中,这不会带来太多好处。
我强烈建议不要使用任何反射黑客,因为它们首先会使使用不可变类型的大多数好处失效。不要给我一个看起来不可变的类型,然后以某种方式偷偷地更改值—这会打破用户的期望并隐藏竞争条件的风险。

相关问题