Combining composite, decorator and visitor patterns

by Antoine Boisier-Michaud   Last Updated December 06, 2018 15:05 PM

I am currently working on a project where I need to manipulate a tree-like data structure, which I implemented with a composite pattern. I want to be able to do different actions on this data structure, so I implemented a visitor pattern.

I was starting to see some code duplication in between my visitors, so I decided to implement a decorator pattern over my visitors. The decorators implement the Visitor interface, and their constructor accepts a Visitor as a parameter.

enter image description here

The idea is that the decorator executes some code before, executes its base visitor (the one passed as a parameter), and executes some code after, a bit like that:

class ConcreteDecorator {
    decoratedVisitor: Visitor

    visitLeaf(leaf) {
        // Do some stuff before
        result := decoratedVisitor.visitLeaf(leaf)
        // Do some stuff after
        return result;
    }

    visitComposite(composite) {
        // Do some stuff before
        result := decoratedVisitor.visitComposite(leaf)
        // Do some stuff after
        return result;
    }
}

The decorator/visitor stuff can be setup like that:

visitor := new ConcreteVisitorA()
visitor := new ConcreteDecoratorA(visitor)
Visitor := new ConcreteDecoratorB(visitor)

The problem is that once I call visitComposite on a decorator, for example, the decorator does its stuff, then calls its child visitor's visitComposite. Since visitComposite is a recursive method, when it is called on the ConcreteVisitor and the method does its recursive calls, we lose the decorators. The decorators are only applied to the first visited node.

I thought of different solutions, like using inheritance instead of decorators, but I want to be able to reuse the decorators on different visitors, so that's not a viable option.

I also thought of using some kind of strategy pattern. The strategies would have a beforeVisitLeaf/afterVisitLeaf and beforeVisitComposite/afterVisitComposite methods. The problem is I can't implement a filter decorator, which abort the visit of certain nodes.

I managed to do a hack this solution and make it work by keeping a hook on the child visitor methods and substituting the child visitor instance methods by the decorator methods manually (I can do that because... JavaScript).

This solution is super hacky, so I was wondering if you guys had any design ideas on how to fix this.



Related Questions


Is it OK to use the Visitor pattern for queries?

Updated February 21, 2017 15:05 PM

Is Visitor Pattern valid in this scenario?

Updated May 21, 2015 22:02 PM

Design Pattern for a an ownership evaluator

Updated August 15, 2017 09:05 AM

Idiomatic pattern matching equivalent in Java

Updated May 11, 2016 08:02 AM

Visitor Pattern, replacing objects

Updated March 26, 2016 08:02 AM