If for example I have a builder set up so I can create objects like so:
Node node = NodeBuilder()
.withName(someName)
.withDescription(someDesc)
.withData(someData)
.build();
How can I make sure that all variables used to build the object have been set before the build method?
Eg:
Node node = NodeBuilder()
.withName(someName)
.build();
Isn't a useful node because the description and data haven't been set.
The reason I'm using the builder pattern is because without it, I'd need a lot of combination of constructors. For example the name and description can be set by taking a Field
object, and the data can be set using a filename:
Node node = NodeBuilder()
.withField(someField) //Sets name and description
.withData(someData) //or withFile(filename)
.build(); //can be built as all variables are set
Otherwise 4 constructors would be needed (Field, Data), (Field, Filename), (Name, Description, Data), (Name, Description, Filename). Which gets much worse when more parameters are needed.
The reason for these "convenience" methods, is because multiple nodes have to be built, so it saves a lot of repeated lines like:
Node(modelField.name, modelField.description, Data(modelFile)),
Node(dateField.name, dateField.description, Data(dateFile)),
//etc
But there are some cases when a node needs to be built with data that isn't from a file, and/or the name and description are not based on a field. Also there may be multiple nodes that share the same values, so instead of:
Node(modelField, modelFilename, AlignLeft),
Node(dateField, someData, AlignLeft),
//Node(..., AlignLeft) etc
You can have:
LeftNode = NodeBuilder().with(AlignLeft);
LeftNode.withField(modelField).withFile(modelFilename).build(),
LeftNode.withField(dateField).withData(someData).build()
So I think my needs match the builder pattern pretty well, except for the ability to build incomplete objects. The normal recommendation of "put required parameters in the constructor and have the builder methods for the optional parameters" doesn't apply here for the reasons above.
The actual question: How can I make sure all the parameters have been set before build is called at compile time? I'm using C++11.
(At runtime I can just set a flag bits for each parameter and assert that all the flags are set in build)
Alternatively is there some other pattern to deal with a large number of combinations of constructors?
build
function throw an exception if a mandatory field is not set. I can't think of any way to make it a compile-time check. – BlindfishwithX
function returns a different type evaluation ofbuild()
could check (at compile time) if conditions are fulfilled. But all that's quite a challenge. – Ritualize