This is a usual pattern I follow. However, I'm constrained by a third party system that requires an instance of the object to be initialised via a no-args public constructor.
It will then be 'properly' initialised by a (non-static) builder at the appropriate place.
What do people think of allowing this? It seems dirty but can't quite put my finger on how dirty!
The builder pattern is good. If there's no way around having a public no-args constructor for that third-party system, then at least describe in the Javadoc documentation for that constructor why it's there, that it's only purpose is to be used by the third-party system, and that developers should not use it directly.
You could also invent a solution where you let the third-party system not initialize your immutable object itself, but another intermediary object, and then you create your immutable object from that when the third-party system has done its job. That would however make your software more complex, so you'd have to decide if it's worth the trouble, and depending on the details of how everything works it might not even be possible.
if the immutable class is being implemented, i.e. hasn't been implemented yet, why does the third party system have already decided to construct it according to its own way, not according to your supplied instantiating way. it's supposed to use your class by its existing layout, i think it's a design issue.
This is common for frameworks that use reflection to initialize objects. They expect the object to have a non-args constructor, and have setter methods for the properties. The framework reads a configuration file that describes which class to instantiate and which properties to set. A very common example is java.util.logging. For the most part Logger should be immutable, but it's not. You should use the static builder to get a logger, and then use it to log. The static builder reads the logging properties and initializes the logger object. Most applications don't change the logging properties at runtime. However, the reason logger is not made immutable is because the static builder itself needs setter methods
The way I approach a problem like this is by having an immutable interface. For the most part, you want immutability because you want to delineate the code:- This factory module is responsible for initializing the object. All these other modules use the object but don't modify it. So, what I do is introduce an interface with only getter methods. All the modules that use the object are coded to the immutable interface. The actual implementation itself is mutable. The factory itself knows the concrete class and knows knows that the concrete class is mutable, and it takes advantage of mutability of the object to initialize it.
Jayesh A Lalwani wrote:For the most part Logger should be immutable, but it's not. You should use the static builder to get a logger, and then use it to log. The static builder reads the logging properties and initializes the logger object. Most applications don't change the logging properties at runtime. However, the reason logger is not made immutable is because the static builder itself needs setter methods.
Surely that doesn't stop the Logger class itself from being immutable?
I use Builders quite a lot when I've got complex objects, but it doesn't stop the object itself from being immutable after I've run build().
But I'm not familiar with Logger, so I may be missing something.
Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
java.util.logging.Logger is mutable. The API allows the application to change logging levels and add and remove handlers at run time, although it really shouldn't. IMO, it should have been an immutable interface rather than an object.