简体   繁体   中英

Java - method vs constructor arguments

I have recently been thinking about the following design consideration: let's say I have an object that is able to read in a file and return some result. Would you say this object should rather expose an interface:

void readFromFile(File file);

or would you design it to have a method

void readFromFile();

and provide necessary values in constructor? The second option seems to be fine if we want to have multiple parameters for constructor and use a builder to build fileReaders based on some user preferences... What do you think?

It depends on the wider context of the object.

If your object is highly cohesive, ie it has a narrow scope in its purpose which is primarily to read from a particular file, then it should be defined in the constructor. In terms of OO design, high cohesion is generally a good thing - so I'd generally favour this option. If your application is multi-threaded and thus your object needs to be thread safe, then I'd definitely lean towards this - I'd argue this approach makes it easier to build granular, immutable objects which is a great help when trying to avoid race hazards.

If your object is responsible for many other tasks, you don't really need to worry about concurrency, and it doesn't really make sense for the file to be included as part of the state of the actual object, then the method that takes the parameter would arguably be the best choice.

I think this is a question about what your object is representing.

You should wonder yourself if it has any meaning to have an instance of what your object models without the file.

Think about your object's responsibility, use the "taking the object to the desert" method: try to think what your object is, and what things it should know. Just then you'll have your answer.

First solution is the cleanest.

However, there's a big difference when dealing with multithreading.

Two cases:

Your class is supposed to be instantiated once:

If your object isn't immutable and own file object as a field, a lot of synchronisations (locks) has to be made to avoid surprises.

Your class is supposed to be instantiated N times

N times for N threads => may be demand a lot of memory depending on your requirement and the weight of the instance.


Thus, the API void readFromFile(File file); is more suitable since file would be local to each thread.

Actually, if your class owns a lot of methods manipulating the file object, and concurrency and memory spaces aren't the primary priority, make the file an instance's field. This would clean your code.

It really depends where this object is going to be used- if this is for a program where there are only one or two files being read, and they're being read a number of times, then the second option would be better; in almost all other scenarios, the first would prevail, as you could use a single object to read a number of files.

Then again, if you plan on using this class in a number of programs (or even distributing it) and therefore are unsure of which method would be best beforehand, there's no reason why you can't include both- have two constructors (one default one, and one that takes a file), and then include both of the methods you listed above- that way the class could be effectively used in either type of program.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM