更新 12/8:回答评论
问题:如果 FileReader 是非常基本的东西,比如 Logging,需要
在每个班级都在那里。你会建议我采用同样的方法吗
那里?
视情况而定。
在进行这样的大规模重构之前,您可能需要考虑一些事情。
-
如果我将FileReader 移到外面,我是否有一个合适的类可以从文件中读取并将结果提供给每个需要它们的类?
李>
除了让课程更易于测试之外,我还有其他好处吗?
我有时间吗?
如果任何一个答案是“否”,那么你最好不要这样做。
但是,我们仍然可以通过最小的更改来打破所有类和FileReader 之间的依赖关系。
根据您的问题和评论,我假设您的系统使用 FileReader 作为从属性文件中读取内容的全局参考,然后将其提供给系统的其余部分。
Michael Feathers 的精彩书中也介绍了这种技术:Working Effectively with Legacy Code,再次。
步骤 1. 将 FileReader 静态方法委托给实例。
改变
public class FileReader {
public static FileReader getMemberOne() {
// codes that read file.
}
}
到
public class FileReader {
private static FileReader singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
public String getMemberOne() {
// codes that read file.
}
}
通过这样做,FileReader 中的静态方法现在不知道如何getMemberOne()
步骤 2. 从FileReader 提取接口
public interface AppProperties {
String getMemberOne();
}
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
@Override
public String getMemberOne() {
// codes that read file.
}
}
我们将所有方法提取到AppProperties,而FileReader 中的静态实例现在使用AppProperties。
第 3 步。静态设置器
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
...
...
}
我们在 FileReader 中打开了一个接缝。通过这样做,我们可以在FileReader 中设置更改底层实例,它永远不会注意到。
第 4 步。清理
现在FileReader 有两个职责。一种是读取文件并提供结果,另一种是为系统提供全局参考。
我们可以将它们分开并给它们一个好的命名。结果如下:
// This is the original FileReader,
// now is a AppProperties subclass which read properties from file.
public FileAppProperties implements AppProperties {
// implementation.
}
// This is the class that provide static methods.
public class GlobalAppProperties {
private static AppProperties singleton = new FileAppProperties();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
public static String getMemberOne() {
return singleton.getMemberOne();
}
...
...
}
结束。
在此重构之后,无论何时您想进行测试。您可以将模拟 AppProperties 设置为 GlobalAppProperties
如果您想要做的只是打破许多类中的相同全局依赖关系,我认为这种重构会更好。