This is cool, but I'm disappointed to see the horrid builder pattern show up again. Imagine you had to use StringBuilder every time you wanted to manipulate a String?
Just make all fields final and combine the builder and 'working' class into a single immutable object. Like String.
`build()` everywhere is syntactic noise, and you either lose immutable safety (by passing around builders everywhere, as in the examples) or composability (by passing around the 'sealed' objects). Builders are an antipattern that should only be used in cases where extreme performance is required.
With immutable objects, every step in the fluent chain of calls is an independent fork of the full object state. There's no need to use java clone(); each method calls a private constructor that passes the object state (slightly altered, of course).
java.lang.String works exactly this way. You're already used to the pattern.
In the parent's suggestion, you still have immutable objects. "VerbalExpression()" is a valid regex, namely the empty one. Every subsequently called method concatenates some new regex onto the receiver and thus builds a new regex (since regular expressions are closed under concatenation).
Builders are used in Java* when you have an object which is invalid without passing in a bunch of parameters, but you don't want to have to remember the order of the parameters. But this is not one of these cases.
There is one drawback, however: you do have to compile the regex into a FSA at some point and it wouldn't be good to do that for every intermediate regex. So I assume that the compilation happens in the "build" step. They could have just called it "compile", though.
* named parameters in constructors seem a better alternative in every language that supports them, e.g. Kotlin
I wish you were interviewing me. This is Java world you're talking about and if you can't squeeze a dozen Gamma Design Patterns into your code you aren't good enough.
Just make all fields final and combine the builder and 'working' class into a single immutable object. Like String.
`build()` everywhere is syntactic noise, and you either lose immutable safety (by passing around builders everywhere, as in the examples) or composability (by passing around the 'sealed' objects). Builders are an antipattern that should only be used in cases where extreme performance is required.