我最近一直在考虑以下设计考虑:假设我有一个能够读取文件并返回一些结果的对象。你会说这个对象应该暴露一个接口吗:
void readFromFile(File file);
或者你会设计它有一个方法
void readFromFile();
并在构造函数中提供必要的值?如果我们想为构造函数设置多个参数并使用构建器根据某些用户偏好构建文件读取器,则第二个选项似乎很好......你怎么看?
我最近一直在考虑以下设计考虑:假设我有一个能够读取文件并返回一些结果的对象。你会说这个对象应该暴露一个接口吗:
void readFromFile(File file);
或者你会设计它有一个方法
void readFromFile();
并在构造函数中提供必要的值?如果我们想为构造函数设置多个参数并使用构建器根据某些用户偏好构建文件读取器,则第二个选项似乎很好......你怎么看?
这取决于对象的更广泛的上下文。
如果您的对象是高度内聚的,即它的目的范围很窄,主要是从特定文件中读取,那么它应该在构造函数中定义。就 OO 设计而言,高内聚通常是一件好事——所以我通常倾向于这个选项。如果您的应用程序是多线程的,因此您的对象需要是线程安全的,那么我肯定会倾向于这一点——我认为这种方法可以更容易地构建粒度、不可变的对象,这在试图避免时很有帮助种族危险。
如果您的对象负责许多其他任务,那么您真的不需要担心并发性,并且将文件作为实际对象状态的一部分包含在内没有任何意义,那么采用的方法该参数可以说是最佳选择。
我认为这是一个关于你的对象代表什么的问题。
您应该想知道在没有文件的情况下拥有对象模型的实例是否有任何意义。
想想你的对象的责任,使用“把对象带到沙漠”的方法:试着想想你的对象是什么,它应该知道什么。到时候你就会有答案了。
第一个解决方案是最干净的。
但是,在处理多线程时有很大的不同。
两种情况:
你的类应该被实例化一次:
如果您的对象不是不可变的并且拥有file
作为字段的对象,则必须进行大量同步(锁定)以避免意外。
你的类应该被实例化 N 次
N 次线程 => 可能需要大量内存,具体取决于您的要求和实例的权重。
因此,APIvoid readFromFile(File file);
更适合,因为file
它对每个线程都是本地的。
实际上,如果您的类拥有很多操作file
对象的方法,并且并发和内存空间不是主要优先级,那么请file
创建实例的字段。这将清理您的代码。
这真的取决于这个对象将被用在哪里——如果这是一个只有一个或两个文件被读取的程序,并且它们被读取了很多次,那么第二个选项会更好;在几乎所有其他情况下,第一个会占上风,因为您可以使用单个对象来读取多个文件。
再说一次,如果您打算在许多程序中使用这个类(甚至分发它),因此事先不确定哪种方法是最好的,那么没有理由不能同时包含两个 - 有两个构造函数(一个默认一个,一个带文件的),然后包含上面列出的两种方法-这样该类就可以在任何一种类型的程序中有效地使用。
IE
public class YourFileReader() {
File defaultFile;
public YourFileReader() {
//initialize
}
public YourFileReader(File aDefault) {
defaultFile = aDefault;
//initialize
}
public void readFromFile() {
if(defaultFile!=null) {
//read from defaultFile
}
else {
//exception?
}
}
public void readFromFile(File file) {
//read from file
}
}