Другим подходом является принятие модели push, а не модели pull. Как правило, вам нужны различные форматтеры, потому что вы нарушаете инкапсуляцию, и есть что-то вроде:
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. Он мог бы даже делегировать другую стратегию раковины внутри страны. Но раковина не обязательно должна заботиться о типе транспортного средства, а только о том, как представлять данные в некотором формате. Использование интернированных глобальных идентификаторов, а не встроенных строк помогает снизить стоимость вычислений (имеет значение только при написании ASN.1 или других жестких форматов).
Возможно, лучше переименовать IVehicleFormatterVisitor только в IVehicleVisitor, поскольку это более общий механизм, чем просто для форматирования. – Richard
вы абсолютно правы. –
Удобное решение. +1 –