Daily Patterns #15

download Daily Patterns #15

of 3

Transcript of Daily Patterns #15

  • 7/31/2019 Daily Patterns #15

    1/3

    VISITOR DESIGN PATTERN

    INTENT

    Represent anoperation to be

    performed on theelements of an objectstructure. Visitor lets

    you define a new

    operation withoutchanging the classesof the elements onwhich it operates.

    The classic techniquefor recovering losttype information.

    Do the right thingbased on the type of

    two objects.

    Double dispatch

    Problem

    Many distinct andunrelated

    operations need tobe performed onnode objects in aheterogeneous

    aggregatestructure. You wantto avoid polluting

    the node classeswith these

    operations. And, youdont want to have

    to query the type ofeach node and castthe pointer to the

    correct typebefore performing

    the desiredoperation.

    Visitorsprimary purpose is to abstract

    functionality that can be applied toan aggregate hierarchy of elementobjects. The approach encourages

    designing lightweight Element classes- because processing functionality is

    removed from their list ofresponsibilities. New functionality

    can easily be added to the originalinheritance hierarchy by creating a

    new Visitor subclass.

    Visitor implementsdouble dispatch. OO messages

    routinely manifest singledispatch - the operation that is

    executed depends on: the name ofthe request, and the type of the

    receiver. In double dispatch, theoperation executed depends on: thename of the request, and the type

    of TWO receivers (the type of theVisitor and the type of the

    element it visits).

    The implementationproceeds as follows. Create a

    Visitor class hierarchy that defines apure virtual visit() method in the

    abstract base class for each concretederived class in the aggregate node

    hierarchy. Each visit() method accepts asingle argument - a pointer or

    reference to an original Elementderived class.

    Each operation tobe supported is modelled witha concrete derived class of the

    Visitor hierarchy. The visit()methods declared in the Visitor

    base class are now defined in eachderived subclass by allocating thetype query and cast code in theoriginal implementation to theappropriate overloaded visit()

    method.

  • 7/31/2019 Daily Patterns #15

    2/3

    Add a single purevirtual accept() methodto the base class of

    the Element hierarchy.accept() is defined to

    receive a singleargument - a pointer or

    reference to theabstract base class of

    the Visitor hierarchy.

    Each concrete derivedclass of the Element

    hierarchy implements theaccept() method by

    simply calling the visit()method on the concretederived instance of the

    Visitor hierarchy that itwas passed, passing its

    this pointer as the

    sole argument.

    Everything forelements and visitorsis now set-up. When the

    client needs an operationto be performed, (s)he

    creates an instance of theVistor object, calls theaccept() method on each

    Element object, andpasses the Visitor object.

    The accept() methodcauses flow of control

    to find the correctElement subclass. Thenwhen the visit() method

    is invoked, flow ofcontrol is vectored to

    the correct Visitorsubclass. accept()dispatch plus visit()

    dispatch equals doubledispatch.

    The Visitor patternmakes adding new

    operations (or utilities)easy - simply add a newVisitor derived class.

    But, if the subclasses inthe aggregate node

    hierarchy are not stable,keeping the Visitorsubclasses in sync

    requires a prohibitiveamount of effort.

    An acknowledgedobjection to the Visitor

    pattern is that isrepresents a regression

    to functionaldecomposition - separatethe algorithms from the

    data structures. Whilethis is a legitimate

    interpretation, perhaps abetter perspective/

    rationale is the goal ofpromoting non-

    traditional behavior tofull object status.

    The Element hierarchyis instrumented with auniversal methodadapter. The

    implementation ofaccept() in eachElement derived classis always the same. But it cannot be moved tothe Element base classand inherited by allderived classesbecause a reference tothis in the Elementclass always maps tothe base type Element.

    When the polymorphicfirstDispatch() method iscalled on an abstract Firstobject, the concrete type ofthat object is recovered.When the polymorphic

    secondDispatch() method iscalled on an abstract Secondobject, its concrete type isrecovered. The applicationfunctionality appropriate forthis pair of types can now beexercised.

  • 7/31/2019 Daily Patterns #15

    3/3

    1. Confirm that thecurrent hierarchy(known as the Elementhierarchy) will be fairlystable and that thepublic interface ofthese classes is

    sufficient for theaccess the Visitorclasses will require.If these conditions arenot met, then the Visitorpattern is not a goodmatch.

    2. Create a Visitor baseclass with avisit(ElementXxx)method for eachElement derived type.

    3. Add an accept(Visitor)method to the Elementhierarchy. Theimplementation in eachElement derived classis always the same accept( Visitor v ){ v.visit( this ); }.Because of cyclicdependencies, thedeclaration of the

    Element and Visitorclasses will need to beinterleaved.

    4. The Element hierarchyis coupled only to theVisitor base class, butthe Visitor hierarchy iscoupled to eachElement derived class.If the stability of theElement hierarchy is

    low, and the stability ofthe Visitor hierarchy ishigh; consider swappingthe roles of the twohierarchies.

    5. Create a Visitorderived class for eachoperation to beperformed on Elementobjects. visit()implementations willrely on the Elements

    public interface.

    6. The client createsVisitor objects andpasses each to Elementobjects by callingaccept().

    The Visitorpattern represents an

    operation to be performed on theelements of an object structure without

    changing the classes on which it operates. Thispattern can be observed in the operation of a taxi

    company. When a person calls a taxi company(accepting a visitor), the company dispatches a cab

    to the customer. Upon entering the taxi the

    customer, or Visitor, is no longer incontrol of his or her owntransportation, the taxi

    (driver) is.

    The abstract syntaxtree of Interpreter is a

    Composite (thereforeIterator and Visitor are

    also applicable).

    Iterator cantraverse a

    Composite. Visitor canapply an operation

    over a Composite.

    The Visitorpattern is like a

    more powerfulCommand pattern becausethe visitor may initiatewhatever is appropriatefor the kind of object

    it encounters.

    The Visitor

    pattern is theclassic technique forrecovering lost typeinformation withoutresorting to dynamic

    casts.