创建`Copyable`类型的接口而不是使用`Cloneable`是否有意义?

时间:2019-06-29 00:37:17

标签: java design-patterns

我有一些代码需要发送对象的副本。之所以如此,是因为调用的服务(运行时库)会修改发送的对象。万一下面的doThing方法需要设置ImportantObj类中的任何字段,此对象还需要公开setter。此实现有待更改,但没有合理的期望在不久的将来进行更改。我的解决方法是提供一个执行以下操作的类:

public class DangerousCallWrapper<T> implements DangerousCaller<T> {
  public T doThing(T dataObject) {

      T cloneOfDataObject = #Clone of dataObject

      // This service modifies the cloneOfDataObject... dangerous! 
      Optional<T> result = service.doThing(cloneOfDataObject);

      return result.orElseThrow(() -> new RuntimeException("No data object returned);
  }
}

public interface DangerousCaller<T> {

  /**
  * Performs the functionality of the DangerousService
  */
  public T doThing(T);
}


public DangerousService<T> {


  public T doThing(T data) {
   data.importantField = null;
   data.thing = "Done!";

   return data;
  }
}

public static void main() {

  DangerousService service = new DangerousService<ImportantObj>();
  ImportantObj important = new ImportantObj().setImportantField("Password for my bank account").setThing("Undone");
  service.doThing(important);
  //would fail this check
  assertNotNull(important.importantField);

  DangerousCallWrapper wrapper = new DangerousCallWrapper<ImportantObj>();
  ImportantObj important = new ImportantObj().setImportantField("Password for my bank account").setThing("Undone");
  service.doThing(important);
  //would not fail this check
  assertNotNull(important.importantField);
}

因此该方法的第一行是我遇到的问题。这是一个泛型类型,因此我无法显式调用某些克隆实用程序,例如Jackson或类似的程序。

所以我以为我只会在方法中添加T extends Cloneable ...但是我打开了Cloneable禁忌(https://www.artima.com/intv/bloch13.html)以外的蠕虫罐。我还读过,复制构造函数可能是处理此问题的最佳方法...但是,我不确定如何使用泛型来表示这一点。

所以我的想法是提供一个接口Copyable来完成您期望Cloneable要做的事情:公开一个方法copy(),该方法将创建类的新实例。

这构成可行的方法吗?

1 个答案:

答案 0 :(得分:1)

要解决您的问题,您需要像这样复制dataObject的副本:

T cloneOfDataObject = dataObject.clone();

,问题是Cloneable没有clone()方法,因此上面的代码无法编译。

在此前提下,创建定义Copyable方法的自己的clone()接口是有意义的,这样您就可以利用已实现的clone()方法(如果存在)数据对象的类。为了获得最佳效果,该接口也必须是通用的:

interface Copyable<T> {
    public T clone();
}

和类型绑定:

public class DangerousCallWrapper<T extends Copyable<T>> 
    implements DangerousCaller<T> {