Re: Builders/Factories and Inheritance.
On Sat, 16 Aug 2008, Daniel Pitts wrote:
I was just thinking about the Builder pattern (because of Roedy's recent
post).
Stop - digression time! I get the impression that there are at least two
different patterns that go by the name 'Builder'.
I don't own a copy of the Gang of Four book, so i can't check what they
wrote, but i think they describe something that's a bit like the
relationship between an XML parser and a DocumentFactory, where you have a
Director that knows what steps have to be performed, and a Builder that
knows how to execute the steps, and where the steps ultimately yield a
complex Product of some sort. To put it another way, the Builder provides
the primitives, and the Director uses the primitives. This allows
decoupling of organisation and the details of the representation - in the
XML case, the factory can build DOM nodes optimised for size, or for
speed, or with javascript support, or using some persistence technique to
transparently handle huge documents, or whatever.
The other pattern, which i *think* might originate in a talk by Josh
Bloch, is where a Builder is essentially a mutable, fairly passive holder
for state that is then used to construct some Product in a single big-bang
constructor invocation. The point of this is that you can make creation of
the Product easier without having to allow partially-constructed Products
to exist.
Here's an example of the first builder (sorry that this is so long-winded,
but it's a complicated pattern):
interface Document {
public List<Element> getElements() ;
}
interface Element {
public String getText( ;
}
interface Heading extends Element {
public int getLevel() ;
}
interface Paragraph extends Element {
}
interface DocumentBuilder {
public void addHeading(int level, String text) ;
public void addParagraph(String text) ;
public Document getDocument() ;
}
// details omitted due to tediousness
class HTMLDocument implements Document // ...
class HTMLElement implements Element // ...
class HTMLHeading implements Heading // ...
class HTMLParagraph implements Paragraph // ...
class PDFDocument implements Document // ...
// etc for PDF versions of other interfaces
class OlympicAwardDirector {
public Document make(DocumentBuilder builder, String athlete, String event, MedalLevel level)
builder.addHeading(1, "Certificate of Olympic Award") ;
builder.addHeading(2, "Preamble") ;
builder.addParagraph("Mumble mumble er Beijing 2008"
+ " spirit of sportsmanship etc") ;
builder.addHeading(2, "Details of Award") ;
builder.addParagraph("This is to certify that a " + level
+ " medal has been awarded to " + athlete
+ " in the " + event) ;
builder.addParagraph("God Save Chairman" Mao") ;
return builder.getDocument() ;
}
}
void someClientMethod() {
DocumentBuilder db = new PDFDocumentBuilder() ;
OlympicAwardDirector dir = new OlympicAwardDirector() ;
Document cert = dir.make(db, "Rebecca Adlington", "800m freestyle", MedalLevel.GOLD) ;
}
Here's an example of the second:
class Medal {
public Medal(MedalLevel level, Event event, String athlete, Nation nation ) // ...
}
class MedalBuilder {
private MedalLevel level
private Event event ;
private String athlete ;
private Nation nation ;
public void setLevel(MedalLevel level) {
this.level = level
}
public void setEvent(Event event) {
this.event = event ;
}
public void setAthlete(String athlete) {
this.athlete = athlete ;
// just to make things interesting:
this.nation = Nation.getForAthlete(athlete) ;
}
public Medal build() {
return new Medallevel, event, athlete, nation() ;
}
}
void someClientMethod() {
mb.setAthlete("Rebecca Adlington") ;
mb.setEvent("800m freestyle") ;
mb.setLevel(MedalLevel.GOLD) ;
Medal m = mb.build() ;
}
Digression over - this is not really an answer to your question. Your
design seems to include some of both. Perhaps this is not uncommon.
It seems to me that Builders are a special type of Factory, and in general
Factories /tend/ to prevent the client from specifying the actual
implementation to use. I was thinking about ways to give the client some
control, while allowing the builder to do its job as-well.
I was thinking of a double-indirection factory (bad name maybe?)
What you've got here is a combination of Builder and Decorator. Sort of.
This seems like it *might* be an anti-pattern, but I'm not sure. Have
any of you had to implement this design? How did it work out? I don't
actually have any real code for this, since I'm just thinking "out loud"
at the moment.
I've never written a class complicated enough to need this sophisticated a
construction pattern, but imagine if i did, it would be a good solution.
The major alternative is to subclass FooBuilder to make SpecialFooBuilder,
adding the extra fields and setters, and then overriding the build()
method. That would, i think, be simpler, but i think your approach is
cleaner. Also, it's compatible with the use of the first style of Builder
above, in that the kind of FooBuilder can be varied, while using the same
SpecialFooBuilder. Although in your case, the FooBuilder is really a
Director. I think.
tom
--
Eat whip you steroid wall-bashing lug-head! -- The Laird