I have a Java app with three classes: Foo
, Bar
and Baz
. All three depend on a bunch of what are currently constants defined in each class in order to determine how to run. On top of that, Baz
interacts with a number of builder classes that need to be set up in various ways.
I’d like to refactor out all of the configuration info in to a .properties file so that I don’t have to recompile every time I change a constant.
But I’m not sure how to structure it:
Do I have a ConfigInfoSingleton
that holds all of the parameters of the application in static properties, and have other classes ask it for information when they need it? That seems wrong, as it introduces global state.
Do I pass around a ConfigInfoMap
as a parameter to all of the classes that need that info? Then I need to have Foo
, Bar
, and Baz
parsing strings in order to decide what they’re going to do, and that seems very wrong. Especially in the case of Baz
, where I can’t just pass around values, but I need to use switch
statements on configuration info to determine builder method calls.
Do I parse the info in a different class, and have that class tell the others how to set themselves up? Then I have a class that needs to know about everyone else’s implementation details, which seems wrong, but less so than the other options.
This seems like a really basic question but I’m not sure how to proceed in terms of good software design, and I haven’t had much luck Googling. Whats the “right” thing to do?
5
As Doval mentions you could parse your *.properties
file and create a class that represents your properties and then pass it along to your classes.
A different approach is also to look into a framework that can handle this for you. Spring does not only inject your dependencies but also handles properties very well. This questions gives a good example on how to use Spring together with *.properties
files.
There is also less intrusive libraries available such as Owner that supports live reloading of your properties amongst other things.
1
Parse the config file and create an object representing the config file’s values. Then you can decide how to construct Foo
, Bar
, and Baz
based on the the values of the object’s fields.
Been there. Done that.
What I did when I had a similar situation was:
Regarding the configuration:
- Created a wrapper around a
Properties
class, I called that wrapperContext
- That wrapper reads and parses the property file
- I created a
ContextDependand
interface with asetContext(Context c)
method - I have
Foo
,Bar
andBaz
implement that interface - I inject that
Context
object into myFoo
,Bar
andBaz
classes so they can acces it without it being a Singleton
Regarding the creation problem:
- I used the
Builder pattern
- I created a Builder interface with just a build method
- Created a FooBuilder, a BarBuilder, a BazBuilder, etc. that implement Builder and return an object which is a superclass of my other classes or an interface they implements
- I added each builder to a HashMap with a key, like
map.put('FOOBUILDER',new FooBuilder())
- Then, instead of a long
case
structure, I just look up the builder in theHashMap
and get it build the object for me, or I traverse the hash and build all of them - That way I tell in the properties files what objects of a collection to build and that can be done without recompiling
If the Builder part is not want you were asking for, at least try the property wrapper / context injection part.