@XingdingCAO
2018-02-12T19:07:23.000000Z
字数 1895
阅读 1889
design-pattern
OOD
初次接触builder
是在Effective Java(2nd Edition)一书中的item 2,后来又在JAXP提供的DOM解析器中遇到了DocumentBuilder
这一个创建Doucment
模型的类。见得越多,我却越迷糊,builder
到底指的是什么?
Gof的Design Pattern一书总结了builder
这一设计模式。
该模式的设计初衷是:“Separate the construction of a complex object from its representation so that the same construction can create different representations. ”也就是说将创建过程与表示分离,相同的创建过程却可以得到不同的表示。
所谓“创建过程”只有当创建的实例非常复杂时才易被感知,而“表示”则是我们最终得到的实例内部数据表示(例如:顺序表可以由数组、链表等实现,这就是对象的不同表示)。
其实现类图如下,Builder
是执行创建步骤的抽象类/接口,而Director
类是指导创建步骤的执行次序或是否执行的指挥。通过对Builder
不同的实现,相同的创建步骤可以产生不同的实例(也就是表示)。
(图片源自《设计模式Java版》)
此处仅讨论部分,若想详细了解,可点击这里。
Effective Java 一书中将Builder
用来创建多字段类的实例,并且借鉴了Fluent API
的思想,将上述的设计模式进行简化,使其更为灵活。但是,设计初衷已经改变,原Builder
是将创建过程与表示分离,而此处的Builder
的创建过程由客户端调用,是为了降低客户端创建复杂对象的难度,而非隔离。
实际做法如图所示:
客户端使用方法如下:
ProductBuilder builder = new ProductBuilder();
Product product = builder.setA(a).setB(b).setC(c).build();
Builder
也可以放入Product
类中成为内部类。
此处的设计方法是在客户端需要建立多字段的类时,提供一种简便的、易懂的方式。
DocumentBuilder
JAXP发行时集成的Sun公司提供的转换功能实现:
public class DocumentBuilderImpl extends implements JAXPConstants
public Document parse(InputSource is) throws SAXException, IOException {
if (is == null) {
throw new IllegalArgumentException(
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
"jaxp-null-input-source", null));
}
if (fSchemaValidator != null) {
if (fSchemaValidationManager != null) {
fSchemaValidationManager.reset();
fUnparsedEntityHandler.reset();
}
resetSchemaValidator();
}
domParser.parse(is);
Document doc = domParser.getDocument();
domParser.dropDocumentReferences();
return doc;
}
//...
}
客户端:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(file);
显然JAXP的DOM解析使用了简化的Builder
模式——无Director
类,将contruct
方法集成到Builder
类中,由Builder
的具体实现类产生Product
实例(此处为Document
的实现类实例)。
在遇到复杂对象的创建问题时,Builder
模式具有其应用的价值,而具体应用应根据其扩展的需要灵活设计,如:JAXP中的DOM解析无Director
类,因为XML文件转换过程有着固定的次序,无需根据类型变动。