Java 如何重构使用到处传递的映射的代码?

Java 如何重构使用到处传递的映射的代码?,java,map,refactoring,Java,Map,Refactoring,现在我正在重构一个遗留的Java项目,现在有一些问题 它定义了一个从Map扩展而来的类名DataHolder,并作为传递类和方法的参数 public class DataHolder extends Map<String,Object> { } public class Cls1 { public void execute(DataHolder data) { data.put("key1", someData); } } public clas

现在我正在重构一个遗留的Java项目,现在有一些问题

它定义了一个从
Map
扩展而来的类名
DataHolder
,并作为传递类和方法的参数

public class DataHolder extends Map<String,Object> {
}

public class Cls1 {
    public void execute(DataHolder data) {
        data.put("key1", someData);
    }
}


public class Cls2 {
    public void execute(DataHolder data) {
        Object someData = data.get("key1");
    }
}

...
公共类数据持有者扩展映射{
}
公共类Cls1{
公共作废执行(数据持有者数据){
data.put(“键1”,someData);
}
}
公共类Cls2{
公共作废执行(数据持有者数据){
objectsomedata=data.get(“key1”);
}
}
...
有30多个类和100多个方法使用这个
数据持有者
实例,对于大多数实例来说,它是唯一的参数

当一个方法生成一些在其他方法中可能需要的值时,它只是将它们放入数据保持器中。如果它需要一些,它只需要从数据持有者那里得到它们

代码很难阅读、测试甚至重构。我正试图重构它,但不知道怎么做


有什么好主意吗?

这是一个元问题,所以我不会在这里编写实际代码。 一种方法是使用单例模式。基本上,它表示您有一个类,该类初始化静态字段中的DataHolder对象,并在每次需要时返回该对象。
您可以删除函数中的所有DataHolder参数,只需在开始时进行这样的调用
DataHolder data=DataHolderSingleton.getInstance()


如果不清楚Singelton的用法或这种方法的好处,我将尝试扩展这个答案。

DataHolder似乎是一种单例,这确实会造成理解和测试代码的问题。可以用来消除单例的一般原则可能适用于您的用例。下面是两个应用于execute方法的示例

Cls2#execute
只需要
数据。获取(“key1”)
-重构过程的第一步是将数据传递给方法:

cls2.execute(dataHolder);
//becomes
cls2.execute(dataHolder.get("key1"));
这样就可以删除所有“只读”依赖项。对于更复杂的示例,需要几个值,传递一个包含所有相关信息的对象可能是有意义的(希望它比数据持有者更专业)

至于
Cls1#execute
它本质上创建了一个新值,因此应该返回它,而不是将它放在全局数据结构中:

public void execute(DataHolder data) { data.put("key1", someData); }
应该是:

public Object execute() { return someData; }

阅读一篇非常有趣的文章:。

您使用的是什么IDE?听起来DataHolder应该是一个字段,而类的执行方法应该是不同的方法。30个类都可以扩展一个公共类,该类引用了这个DataHolder。然后,您可以删除所有函数中的数据保持器参数。@marounnaroun,Intellij IDEAThat只是将一个全局状态替换为另一个全局状态-这并不会使代码更容易理解或更易于测试…我想这只能通过完全去掉数据保持器来实现。因为这种情况不太可能发生,所以我想了一个办法,至少可以让它好一点。你是对的。整个数据持有者问题似乎掩盖了项目背后实际上没有架构。我还打赌@Freewind知道这一点,我们为此同情他:)