2012-11-18 172 views
3

我最近一直在考虑以下设计考虑事项:假设我有一个能够读取文件并返回一些结果的对象。你会说这个对象应该相当暴露的接口:Java - 方法vs构造函数参数

void readFromFile(File file); 

,或者你将它设计有一个方法

void readFromFile(); 

和构造提供必要的值?如果我们想要为构造函数使用多个参数并使用构建器根据某些用户偏好构建fileReaders,则第二个选项似乎没有问题......您怎么看?

+0

第二个选项闻起来像一个静态方法。而且,尽管它们有其用途,但滥用它们对于Java中的非OOP是一种好方法。 – SJuan76

+2

@ SJuan76我假设你的意思是* first *选项'闻起来像是一种静态方法吗? – mmcrae

回答

6

这取决于对象的更广泛的上下文。

如果你的对象是高度内聚的,即它的目的范围很窄,主要是从一个特定的文件读取,那么它应该在构造函数中定义。就面向对象设计而言,高内聚性通常是一件好事 - 所以我通常会赞成这种选择。如果你的应用程序是多线程的,因此你的对象需要线程安全,那么我肯定会倾向于这一点 - 我认为这种方法可以更容易地构建细粒度,不可变对象,这在试图避免时非常有帮助种族危害。

如果您的对象负责许多其他任务,那么您并不需要担心并发性,并且将文件作为实际对象状态的一部分包含在内并没有意义,然后采用参数的方法可以说是最好的选择。

+0

按照我上面的评论 - 在存储进一步读取统计信息并在多线程环境中使用的情况下,选项2会更好吗? – Bober02

+0

请参阅编辑 - 在多线程环境中,我一定会选择1. – berry120

+0

那么,如果一个对象也存储Load统计信息,那么单个方法就没有意义了吗?多个调用者可能会看到一个共享的结果,而不一定是他们的,这取决于竞争条件... – Bober02

1

我认为这是一个关于你的对象代表什么的问题。

您应该好奇自己是否有任何意义,让您的对象在没有该文件的情况下建模。

想想你的对象的责任,使用“把对象带到沙漠”的方法:试着去思考你的对象是什么,以及它应该知道什么事情。就在这时你会得到你的答案。

-1

这实际上取决于这个对象在哪里被使用 - 如果这是一个程序,其中只有一个或两个文件被读取,并且它们被读取多次,那么第二个选项将是更好;在几乎所有其他情况下,第一种情况会占上风,因为您可以使用单个对象来读取多个文件。

如果你计划在很多程序中使用这个类(或者甚至分发它),因此不确定哪种方法最好事先做好,那么你没有理由不能同时包含这两种方法 - 有两个构造函数(一个默认的,一个接受一个文件),然后包含上面列出的两个方法 - 这样,类可以有效地用于任何一种类型的程序。

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

好吧,我打算重复使用它,并考虑以下标准:每个对象都会读入一个文件,然后将读取的统计信息作为其内部状态的一部分存储在单独的对象中。另外,我打算在一个多线程环境中使用这个对象 - 在许多文件中一致地阅读。选项2在这种情况下有意义吗? – Bober02

+0

-1:做同样事情的两种方式?只要正确设计你的模型(注意:这与重载的构造函数无关)。 – SJuan76

+0

这两个选项在线程应用程序中都应该可以很好地工作,但是对于存储有关该文件的统计信息,第二个选项会更好。 但是,根据FileReader类的复杂程度,最终可能会使用大量额外的内存,具体取决于您正在阅读的文件数量 - 如果使用第二个选项的唯一原因是存储文件信息,你可能会更好地将信息存储在其他地方(一个数组或列表保存在别处),而不是保留大量的FileReader。完全取决于你的计划,只是一个考虑。 –

1

首先溶液是最干净。

但是,处理多线程时有很大的不同。

两种情况:

你的类应该被实例化一次:

如果你的对象并不是一成不变的和自己的file对象作为一个场,很多synchronisations(锁)有被制造以避免意外。

你的类应该被实例化N次

N次的N个线程=>可能需要根据您的要求和实例的权重了大量的内存。


因此,API void readFromFile(File file);是更适合的,因为file将是本地的每个线程。实际上,如果你的类拥有很多操纵file对象的方法,并且并发和内存空间不是主要优先级,那么将file作为一个实例的字段。这会清理你的代码。

+0

什么是一个存储的负载统计?在一个多线程的env中,这会弄得一团糟,因为每个调用者都会看到(可能)相同的结果,不一定是他们提交的负载,但最后一次调用这个方法 – Bober02

+0

@ Bober02我看不到你所说的“加载统计“。在这种情况下,第一种还是第二种方式? – Mik378

+0

@ Bober02我现在明白你想要什么(通过阅读上面的评论)。因此,有两种解决方案:为每个读取文件创建一个实例,并将一个附加字段指向名为“'Statistics”的类,该类包含文件的检索信息。在第三个对象中创建一个'ConcurrentHashMap',应该用'Statistics'(值)来收集所有文件(键)。这张地图可以通过你的类的方法访问,整个过程只允许你实例化一个实例!所以第一个解决方案也适用 – Mik378