I am currently using the builder pattern as defined here:
Previous question showing my use of the builder pattern
The problem I've now encountered is a requirement to create the following structure:
- ZipHolder: file metadata present
* File mainFile
* File optionalFile
* List<File> files
OR:
- ZipHolder: no file metadata present
* File mainFile
* File optionalFile
* List<File> files
Both ZipHolder
and File
are constructed using the builder pattern, implemented as an internal static class of each. A ZipHolder
takes a mainFile
as a mandatory constructor parameter and prefills some information in the ZipHolder
, which can be overridden, should the need arise. A File
contains file content and associated metadata pertaining to that file. Validation on both the ZipHolder
and File
is then performed when calling the build()
method of each's Builder
class. The objects are then taken and output to a ZIP file hierarchy that should then be read in to the same object structure, if required.
This works nicely and gives a degree of flexibility in object creation while ensuring immutability. I have encountered a problem though. A new requirement has presented itself, mandating that File
objects can either have metadata and file content OR only file content. I figured I could simply pass a boolean flag value to the builder for the ZipHolder
object to allow the skipping of the usual metadata validation. This would seem ok but then it requires a File
mainFile to be constructed - essentially, a chicken and egg situation. My next thought was to move the flag to the File
class. This seemed ok until I realised that you could potentially create multiple File
objects, some with metadata required and others with only the file content, with no means of enforcing constraints across the board.
So I am somewhat stumped as to how to proceed. I can't see an obvious means of decoupling the requirement of a mainFile for a ZipHolder
in an elegant fashion. Concepts like abstract classes, interfaces, base classes and things like that come to mind but I'm in need of some direction in this particular situation.
So my question is:
Can I allow for both scenarios while retaining the builder pattern per the reasons in my link above?