Let's say I have an Object Structure like this that I import data into from a source:
Reporting:
Body:
ReportingEntity:
DocSpec
Reports[]:
ConstEntities[]
DocSpec
AdditionalInfo[]
DocSpec
MessageSpec
Whenever I import the data I have to check for changes in any of the objects and update the DocSpec objects within dependent of the type of change (no change
, correction
, added data
, removed data
). Then I have to split the object and filter the correction
and removed
data into one object and filter added data
into a second object. Each of them will be written to its own XML file and sent to an authority.
On first glance this looks like a great opportunity to use the Visitor Pattern for UpdateReportingVisitor
and FilterReportingVisitor
but I also see a major difference here: A visitor only traverses one object structure and does its operations on it. It doesn't work on a second object simultaneously. An accept()
method for UpdateReportingVisitor
would look like this:
class Body(object):
def accept(self, visitor, other):
"""rough draft to communicate the concept. This is not the actual implementation!"""
visitor.visit_body(self, other)
for self_report, other_report in zip(self.reports, other.reports):
self_report.accept(visitor, other_report)
for self_info, other_info in zip(self.additional_infos, other.additional_infos):
self_info.accept(visitor, other_info)
while FilterReportingVisitor
wouldn't need that extra argument.
I'm a bit uncomfortable with this solution because of that other
argument in each accept()
method that clearly doesn't belong to the pattern. Would this approach still be considered a visitor pattern? (If no: Does it have a different name?) is there a different (better?) pattern to solve the problem i have?
1 Answer 1
Your accept seems to strictly associate children by their position. I'm not sure it is what you really want. It may behave unexpectedly if a child is inserted in middle. Seems like you cannot abstract the specific task from the implementation of accept, if you go this way.
There is an alternative way to define visitors, which leaves descending into children to the visitor. This way, you have much finer control over how do you traverse the data structure. You can process node before visiting children, or after. Or, as in your case, traverse 2 data type in parallel, abstracting the specific logic from the class - for example, you could search for matching children in the list. This, however, would require you to create a many visitor classes, to dispatch in - roughly as many as node types you have, plus one for the first argument dispatch. It's quite a bit of writing, so I cannot provide you an example now.
-
I'm sorry the accept method is just a rough draft, not the actual implementation of it. I should have mentioned that. The actual version has some operations for elements in both lists and also for elements that are only in one of each list.Tekay37– Tekay372018年08月03日 10:04:39 +00:00Commented Aug 3, 2018 at 10:04
Explore related questions
See similar questions with these tags.
accept()
for all visitors in each class i will need at least 2 of those methods in each class. Maybe there will be a third case that will need a third implementation of the visitor pattern one day so I was wondering if this pattern might be wrong abstraction. Your reaction helped me a lot though. Thanks! :-)