另一种方法是采用推模型而不是拉模型。通常你需要不同的格式化程序,因为你打破了封装,并且有类似的东西:
class TruckXMLFormatter implements VehicleXMLFormatter {
public void format (XMLStream xml, Vehicle vehicle) {
Truck truck = (Truck)vehicle;
xml.beginElement("truck", NS).
attribute("name", truck.getName()).
attribute("cost", truck.getCost()).
endElement();
...
您将数据从特定类型提取到格式化程序的位置。
相反,创建与格式无关的数据接收器并反转流程,以便特定类型将数据推送到接收器
class Truck implements Vehicle {
public DataSink inspect ( DataSink out ) {
if ( out.begin("truck", this) ) {
// begin returns boolean to let the sink ignore this object
// allowing for cyclic graphs.
out.property("name", name).
property("cost", cost).
end(this);
}
return out;
}
...
这意味着您仍然封装了数据,并且您只是将标记的数据提供给接收器。然后,XML 接收器可能会忽略数据的某些部分,可能会重新排序其中的某些部分,然后编写 XML。它甚至可以在内部委托给不同的接收器策略。但是 sink 不一定需要关心车辆的类型,只关心如何以某种格式表示数据。使用内部全局 ID 而不是内联字符串有助于降低计算成本(仅在您编写 ASN.1 或其他紧凑格式时才重要)。