I have some classes I've created that are immutable and follow the builder pattern. I'm now creating a composite class that will include those classes as fields. Should the builder for that composite class call through to the sub-builders and then build them in the outer builder's build() method, or should the composite builder have methods that accept already constructed instances of the contained classes, or should I allow both options?
Building a class that contains built classes
design patterns
I'm going to assume your classes are called Composite, Foo, Bar and Baz.The simplest option is to let CompositeBuilder take pre-built Foos/Bars/Bazs, so you get new CompositeBuilder().setFoo(...).setBar(...).setBaz(...).build(). The big advantage here is that the API to your Composite class is dead simple, both for you and your users. KISS and YAGNI apply here. Plus, you still get the option of subclassing Foo/Bar/Baz, and this might make it easier to change Foo/Bar/Baz themselves since Composite doesn't have to know much about them.The alternative of having CompositeBuilder provide it's own interface has other potential advantages, assuming that you provide a much smaller, narrower interface than the one you get for free from the three subbuilders. That can potentially make Composite much easier to work with, and opens the possibility of someday changing Composite to use Oof/Rab/Zab instead of Foo/Bar/Baz without affecting client code, in case subclassing isn't enough.I would avoid providing both, unless you're very sure you have a lot of users that want a simplified interface and a lot of other users who need the full power of a raw FooBuilder. Trying to do too many things at once always runs the risk of doing none of them well (and making it hard for anyone to figure out how they're supposed to use Composite).Which one you should pick depends on a lot of factors you haven't described. How complicated are the three subbuilders? How much customization does a Composite need? Will users of CompositeBuilder already be familiar with the Foo/Bar/BazBuilders? Do they despise the current Foo/Bar/BazBuilder interfaces? Are there separate consumers and producers of these objects, or are they usually used in the same place where they're built? Would it ever make sense to change the classes that Composite is implemented with? And so on and so forth.