Taking what Philipp suggested a step farther, try this.
Given class Widget is the parent, and class Feature is the base type of the child hierarchy
Simple usage:
// widget will have an instance of a Feature subclass from args or config, etc
Widget theWidget = new Widget(args);
// create and configure visitor
Visitor theVisitor = new Visitor();
theVisitor.prop1 = x;
theVisitor.prop2 = y;
theVisitor.prop3 = z;
theWidget.visit(theVisitor);
Widget (parent class):
class Widget
{
Feature _childFeature;
void visit(Visitor visitor)
{
visitor.beginAccept(this);
childFeature.visit(visitor);
visitor.endAccept();
}
}
Feature class hierarchy:
abstract class Feature
{
abstract void visit(Visitor visitor);
}
class Sunroof extends Feature
{
void visit(Visitor visitor)
{
visitor.accept(this);
}
}
class BulletProof extends Feature
{
void visit(Visitor visitor)
{
visitor.accept(this);
}
}
class GoldPlated extends Feature
{
void visit(Visitor visitor)
{
visitor.accept(this);
}
}
A concrete visitor that uses both the parent and the child:
class ExampleVisitor extends Visitor
{
private _widgetInProcess;
void beginAccept(Widget w)
{
_widgetInProcess = w;
}
void accept(Sunroof feature)
{
// do work based on both _widgetInProcess and type-specific feature
}
void accept(BulletProof feature)
{
// do work based on both _widgetInProcess and type-specific feature
}
void accept(GoldPlated feature)
{
// do work based on both _widgetInProcess and type-specific feature
}
void endAccept()
{
_widgetInProcess = null;
}
}
You can visualize the tree model use-case as well where in beginAccept you push onto a stack, the various accept methods peek the stack to get their parent context, and endAccept pops from the stack. This can allow you to recursively process a tree while always having access to the parent chain.