简体   繁体   中英

Preferred method for initializing a child class parameters in Java?

I have an application that takes some input and generates configuration files as output. Since the exact input or output format could change over time, I defined two interfaces: Importer and Exporter.

Each concrete importer or exporter could have different parameters that need to be initialized to work. For example, if the import data is coming from a CSV file you only need the path of the file, but if the data is coming from a database then you need a connection string, username, password, etc. Same thing for exporters.

My implementation currently is:

public interface Importer {
    public void setup(Map<String,String> params);
    public List<ConfigEntry> getList();
}

public interface Exporter {
    public void setup(Map<String,String> params);
    public void writeDocument(List<ConfigEntry> entries) throws IOException;
}

The setup method needs to be called before getList() or writeDocument() can be called. I use a Map to keep parameters because each child class can have different parameters.

Is using JavaBean style parameter initialization a preferred way? That means, adding setConnnectionString(), setCSVFilePath(), setX() to each child class.

What are the advantages, disadvantages of these approaches?

There are two obvious downsides to map-based approach:

  1. Absence of well-defined parameter names. Yes, you could define them as constants somewhere but you'd still need to check that parameter name is valid as passed.
  2. Absence of well-defined parameter types. Even worse then above - if I need to pass an integer I'd have to convert it to String and you'll have to parse it (and deal with possible errors). Can be somewhat mitigated by using Map<String,Object> and auto-bounding but then you'd still need to validate appropriate types.

Setter-based approach has only one downside - it can't be done. That is, it can't be reliably done by using setters ALONE - you need to supplement it with some kind of init() or afterPropertiesSet() method that will be called after all setters and will allow you to perform additional (co-dependent) validation and initialization steps.

Also, something like this practically begs for some kind of Dependency Injection framework. Like Spring , for example.

I wouldn't say that passing a Map (or Properties) object in the constructor is necessarily preferred over child class specific setter, or vice versa. Which approach is best depends on how you are going to instantiate the classes.

If you are going to instantiate the classes directly from Java then the Map approach tends to be neater, especially if you have a good way to assemble the maps. (For example, loading a Properties object from a property file.) The 'setters' approach forces you to write code against each of the child class APIs.

On the other hand, if you are going to instantiate the classes using some container framework that supports "wiring", "inversion of control" or the like (eg Spring, PicoContainer, JavaBeans, etc), then setters are generally better. The framework typically takes care of when and how to instantiate the classes and call the setters, using reflection under the hood to do the work.

So the answer is ... it depends ...

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