+ All Categories
Home > Documents > 06 Design Patterns Visitor

06 Design Patterns Visitor

Date post: 14-Apr-2018
Category:
Upload: trinath-somanchi
View: 215 times
Download: 0 times
Share this document with a friend

of 79

Transcript
  • 7/27/2019 06 Design Patterns Visitor

    1/79

    Software Engineering

    DesignDesign Patterns: VisitorDesign Patterns: Visitor

    Prof. Dr. Mira Mezini

    Dipl.-Inform. Christoph BockischDipl.-Ing. Michael Haupt

  • 7/27/2019 06 Design Patterns Visitor

    2/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Classification of Design Patterns

    Creational Control the way how to create objects

    What examples do you know?

    Structural

    Describe the relation between objects and classes

    What examples do you know?

    Behavioral

    Describe the way how to implement algorithms and communication Has there been an example in the lecture so far?

  • 7/27/2019 06 Design Patterns Visitor

    3/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Case-Study: A WYSIWYG Document

    Editor

    Document represented in the

    central rectangular area

    Document can mix text andgraphics in a variety of

    formatting styles

    User can interact by using

    menu items

  • 7/27/2019 06 Design Patterns Visitor

    4/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Class Diagram of a Documents Elements

    children

    Document

    DocElement

    Character Graphic

    Row Column

    Group

    *

    Do you recognize

    a pattern here?

  • 7/27/2019 06 Design Patterns Visitor

    5/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Extend the current design with

    Capability to support various algorithms that

    Operate on elements of a document In a first prototype, add support for spell

    checking

    Later we might want to add Word counting

    Grammar checking

    Hyphenation

    Etc...

    ! Design should be "open" for future extensions

    Design Issue: Add Processing

    Operations

  • 7/27/2019 06 Design Patterns Visitor

    6/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Class Diagram of a Documents Elements

    children

    Document

    DocElement

    Character Graphic

    Row Column

    Group

    *

  • 7/27/2019 06 Design Patterns Visitor

    7/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Implement spell checking first by adding:

    SpellChecker (has a Dictionary and

    encapsulates state needed during the process)

    Current Design

    GroupIterator

    Iterator

    first() : void

    next() : void

    current(): DocElementisDone() : boolean

    Group

    iterator(): Iterator

    SpellChecker Dictionary

    DocElementchildren

  • 7/27/2019 06 Design Patterns Visitor

    8/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Next: add an operation check(SpellChecker) to

    DocElements interface

    DocElement subclasses implement check in a specific

    way

    Graphics need not spell checking

    Checking a document involves

    An iteration over its elements

    Calling the specific method for each element

    The SpellChecker parameter serves as a workspace

    shared by all specific methods that are called during thisprocess

    Implementing the check() Function

  • 7/27/2019 06 Design Patterns Visitor

    9/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Implementing the check() Function

    childrenchildrenDocElementcheck(SpellChecker ch)

    Character

    check(SpellChecker ch)

    Group

    check(SpellChecker ch)

    Iterator iterator = iterator();iterator.first();while (!iterator.isDone()) {DocElement elem = iterator.current();

    elem.check(ch);iterator.next();

    }

  • 7/27/2019 06 Design Patterns Visitor

    10/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Implementing the check() Function

    childrenchildrenDocElementcheck(SpellChecker ch)

    Character

    check(SpellChecker ch)

    Group

    check(SpellChecker ch)

    char c = getCharCode();if (c.isAlphabetic())

    ch.addToCurrentWord(c);else {

    if (!dictionary.includes(ch.word()){// handle misspelling

    }ch.resetWord();

    }

    Concatenate current word

    When word is done, look it up

  • 7/27/2019 06 Design Patterns Visitor

    11/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Achievements Can spell-check documents

    Handle different DocElements correctly

    Drawbacks DocElement classes need to know about spell checking

    To support new algorithms (word counting, grammar checking)

    Need to modify DocElement and

    Clients ofDocElement classes each time!

    DocElement gets more and more complicated, its design is non-cohesive: it captures too many unrelated features.

    How can we avoid these problems?

    Resume of Current Design

    S f T h l

  • 7/27/2019 06 Design Patterns Visitor

    12/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Why not encapsulate theprocess of spell checkingcompletely withinSpellChecker?

    Encapsulate Spell Checking

    SpellChecker

    checkGroup( DocElement )

    checkCharacter( DocElement )

    ...

    SpellChecker expects the document to bechecked as a parameter; iterates over itselements and checks each individual element.

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    13/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    SpellChecker receives a DocElement in each step ofiteration and needs to distinguish between differentDocElement types

    Characters, Graphics, Groups etc. need to behandled differently

    in the previous design, inheritance (subtype

    polymorphism) ensured that the right checkingoperation was executed for each element

    in the new design, this is not possible anymore

    What mechanism can we use to distinguish betweenDocElement subclasses?

    Determine Element Type

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    14/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Could use the reflective operatorinstanceof in Java or

    dynamic casting in C ++

    The SpellChecker would check the DocElement for

    each subclass that were interested in

    Dynamic Casting

    Determine Element Type (Dynamic Cast)

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    15/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Add a className() operation to the DocElement class

    (C++) or use RTTI (C++) / Reflection (Java)

    Subclasses overload className() to return a string with

    the name of the class for clients to test against

    if(element.className().equals(CHARACTER_CLASS))

    The SpellChecker would retrieve the class for each

    DocElement and see how it can handle the specific

    object

    className() Operation

    Determine Element Type (Dynamic Cast)

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    16/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    class SpellChecker {

    public void checkGroup(DocElement group) {

    Iterator iterator = group.iterator();

    iterator.first();while (!iterator.isDone()) {

    DocElement elem = iterator.current();

    if (elem instanceof Character)checkCharacter(elem);

    else if (elem instanceof Graphic)

    checkGraphic(elem);

    else if (elem instanceof Group)

    checkGroup(elem);

    iterator.next();

    }}} Spell Checking Iteration

    Is this good design?Is this good design?

    Determine Element Type (Dynamic Cast)

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    17/79

    gyGroupTU-Darmstadt | FB Informatik

    Solution so far depends on conditional logic to handle

    different kinds of document elements

    Generally, if there is a design solution that depends on aseries ofif statements or a case statement there is a

    more object-oriented way to solve the problem

    Lets see if we cant use inheritance in some way to

    handle our problem of sorting out the differentsubclasses

    Case / If Statements vs. OO

    Determine Element Type (Dynamic Cast)

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    18/79

    GroupTU-Darmstadt | FB Informatik

    Generalize all operations that process documentaggregates to a common type:Visitor

    Visitor contains an operation for each element type -

    each visitor functionality is split into its element-specificparts

    SpellChecker implements theVisitor interface

    Adding a Visitor Abstraction

    SpellChecker

    visit( Group )visit( Character )

    ...

    Visitorvisit( Group )

    visit( Character )

    ...

    Software Technology

  • 7/27/2019 06 Design Patterns Visitor

    19/79

    GroupTU-Darmstadt | FB Informatik

    How can the spell checker ensure that the rightvisit() gets called without knowing the dynamictype ofelem?

    Iterator iterator =group.iterator();

    iterator.first();

    while (!iterator.isDone()) {DocElement elem =

    iterator.current();visit(elem); ???

    iterator.next();}

    SpellChecker

    visit( Group group )

    visit( Character ch )

    Visitor: Handling Different Subclasses

    let the Java VM do the job forus based on its methodoverloading semantics ...

    Software TechnologyG Vi it H dli Diff t S b l

  • 7/27/2019 06 Design Patterns Visitor

    20/79

    GroupTU-Darmstadt | FB Informatik

    Iterator iterator =group.iterator();

    iterator.first();

    while (!iterator.isDone()) {DocElement elem =

    iterator.current();visit(elem); ???

    iterator.next();}

    Visitor: Handling Different Subclasses

    How can the spell checker ensure that the rightvisit() gets called without knowing the dynamictype ofelem?

    SpellChecker

    visit( Group group )

    visit( Character ch )

    Compile-Time Error!

    Software TechnologyGroup Vi it H dli Diff t S b l

  • 7/27/2019 06 Design Patterns Visitor

    21/79

    GroupTU-Darmstadt | FB Informatik

    Overloaded methods are staticallydispatched. The compiler searchesa method to execute for the callvisit(elem) based on the static

    type ofelem.

    Since there is no methodvisit(DocElement) in

    Visitor's interface anerror will occur.

    Iterator iterator =

    group.createIterator();

    iterator.first();while (!iterator.isDone()) {

    DocElement elem =

    iterator.currentItem();

    visit(elem); ???

    iterator.next();

    }

    Visitor: Handling Different Subclasses

    Compile-Time Error!

    How can the spell checker ensure that the rightvisit() gets called without knowing the dynamictype ofelem?

    Software TechnologyGroup

    Vi it H dli Diff t S b l

  • 7/27/2019 06 Design Patterns Visitor

    22/79

    GroupTU-Darmstadt | FB Informatik Visitor: Handling Different Subclasses

    We need a different implementation For each subclass ofVisitor

    For each subclass ofDocElement

    The concrete types are determined at runtime

    The JVM takes the receivers runtime-type into accountwhen selecting a methods implementation

    We need to dispatch for runtime-type of two objects Soulution: Double Dispatch

    Software TechnologyGroup Visitor Abstraction Adding t()

  • 7/27/2019 06 Design Patterns Visitor

    23/79

    GroupTU-Darmstadt | FB Informatik

    Declare one generic operation in DocElement foraccepting the visit of any processing object rather thanhaving one operation per processing functionality

    SpellChecker

    visit ( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )...

    Visitor Abstraction: Adding accept()

    DocElement

    checkSpelling( SpellChecker )

    checkGrammar(

    GrammarChecker )

    GrammarChecker

    visi t( Group )

    visit( Character )

    ...

    DocElement

    accept( Visi tor v )

    Software TechnologyGroup Visitor Abstraction: Adding t()

  • 7/27/2019 06 Design Patterns Visitor

    24/79

    GroupTU-Darmstadt | FB Informatik

    Concrete DocElementsubclasses implement

    accept(Visitor v) by

    calling v.visit(this) This ensures that the

    specific visit method for the

    concrete element class isinvoked

    SpellChecker

    visit ( Group )

    visit( Character )

    ...

    Visitor

    visi t( Group )

    visit( Character )...

    DocElement

    accept( Visi tor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    v.visit(this);

    Visitor Abstraction: Adding accept()

    Software TechnologyGroup Visitor Abstraction: Adding accept()

  • 7/27/2019 06 Design Patterns Visitor

    25/79

    pTU-Darmstadt | FB Informatik

    Iterator it = group.iterator();

    it.first();

    while (!it.isDone()) {DocElement elem = it.current();

    elem.accept( this );

    it.next();

    }

    Visitor Abstraction: Adding accept()

    First, dispatch for

    DocElements type.

    v.visit(this);

    Second, dispatch for

    Visitors type and call

    visit method which takes

    Chararcter argument.

    v is a SpellChecker and the first element in the group is a Character.

    v.visit(group);

    DocElement

    accept( Visitor v )

    Group

    accept( Visitor v )

    Character

    accept( Visitor v )

    dynamic

    static

    SpellChecker

    visit ( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    GrammarChecker

    visi t( Group )

    visit( Character )

    ...

    static

    dynamic

    Software TechnologyGroup Visitor Abstraction: Adding accept()

  • 7/27/2019 06 Design Patterns Visitor

    26/79

    TU-Darmstadt | FB Informatik

    All accept operations have the sameimplementation. Shouldn't I define

    accept(Visitor v) once in DocElementand let subclasses inherit it?

    Visitor Abstraction: Adding accept()

    DocElement

    accept( Visitor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    v.visit(this);

    Software TechnologyGroupT | f i Visitor Abstraction: Adding accept()

  • 7/27/2019 06 Design Patterns Visitor

    27/79

    TU-Darmstadt | FB Informatik Visitor Abstraction: Adding accept()

    DocElement

    accept( Visi tor v )

    Character Group

    v.visit(this);

    Compile-Time Error!

    Again, the compiler uses the static type ofthis to decide

    that visit(DocElement) should be called. But there is nosuch operation inVisitor's interface!

    Software TechnologyGroupTU Darmstadt | FB Informatik Advantages of the Visitor Abstraction

  • 7/27/2019 06 Design Patterns Visitor

    28/79

    TU-Darmstadt | FB Informatik

    Minimal interface between element types and all kinds ofprocessors (existing and future ones) operating on them

    The only thing known to DocElement (and subtypes) is

    that they can "accept" the visit of objects that implementVisitor

    Concrete type of visitors passedat runtime remains unknown

    SpellChecker

    visit( Group )visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    GrammarChecker

    visit( Group )visit( Character )

    ...

    DocElement

    accept( Visitor v )

    Advantages of the Visitor Abstraction

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Advantages of the Visitor

  • 7/27/2019 06 Design Patterns Visitor

    29/79

    TU-Darmstadt | FB Informatik

    Adding support for hyphenation merely requiresadding a newVisitor class... Existing classes donot change!

    Abstraction

    SpellChecker

    visi t( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    GrammarChecker

    visi t( Group )

    visit( Character )

    ...

    DocElement

    accept( Visitor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    Hyphenator

    visit ( Group )

    visit( Character )

    ...

    Software TechnologyGroupTU-Darmstadt | FB Informatik The Visitor Pattern

  • 7/27/2019 06 Design Patterns Visitor

    30/79

    TU Darmstadt | FB Informatik

    Represent operations to be performed on theelements of an object structure as an object

    New operations can be added without changingthe classes of the elements on which they

    operate

    The Visitor Pattern

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Visitor Pattern Class Diagram

  • 7/27/2019 06 Design Patterns Visitor

    31/79

    |

    ConcreteVisitor1

    visit( ElementA )

    visit( ElementB )

    Visitor

    visit( ElementA )

    visit( ElementB )

    ConcreteVisitor2

    visit( ElementA )

    visit(ElementB )

    Element

    accept( Visi tor )

    ElementA ElementB

    Visitor Pattern Class Diagram

    Client

    ObjectStructure

    accept( Visitor ) accept( Visitor )

    *

    Alteratives: ObjectStructure

    provides iterator or visiting.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Participants

  • 7/27/2019 06 Design Patterns Visitor

    32/79

    Visitor declares a "visit" function for each Element

    subclass to be visited

    an abstract base class for different types ofvisitors

    ConcreteVisitor

    implements theVisitor abstract interface

    provides a concrete implementation for aspecific visiting algorithm

    Visitor Pattern Participants

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Participants

  • 7/27/2019 06 Design Patterns Visitor

    33/79

    Element

    abstract base class for various element subclasses

    defines an accept() function that takes aVisitoras an argument

    ConcreteElement

    implements the accept() function and calls the

    appropriate Visitor function for this

    ConcreteElement

    Visitor Pattern Participants

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Participants

  • 7/27/2019 06 Design Patterns Visitor

    34/79

    ObjectStructure contains multiple Elements (may be a Composite

    or any other type of aggregate of elements)

    may provide an iterator to iterate through its elementsor may provide a high-level visiting function

    Visitor Pattern Participants

    Software TechnologyGroupTU-Darmstadt | FB Informatik ObjectStructure/Client Interface

  • 7/27/2019 06 Design Patterns Visitor

    35/79

    ObjectStructure

    iterator()

    j

    Element

    accept(Visitor)

    VisitorClient

    ConcreteVisitorIterator

    ObjectStructure provides an Iterator

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Interaction

  • 7/27/2019 06 Design Patterns Visitor

    36/79

    iteriter== iteratoriterator()()

    anObjectStructureanObjectStructure elementAelementA elementBelementB visitorvisitor

    accept(visitor)accept(visitor)visit(elementAvisit(elementA))

    accept(visitor)accept(visitor) visit(elementBvisit(elementB))

    aClientaClient iteriter

    elementAelementA = next()= next()

    elementBelementB = next()= next()

    External iterator

    Software TechnologyGroupTU-Darmstadt | FB Informatik ObjectStructure/Client Interface

  • 7/27/2019 06 Design Patterns Visitor

    37/79

    j

    ObjectStructure

    accept(Visitor)

    Element

    accept(Visitor)

    VisitorClient

    ConcreteVisitor

    *

    ObjectStructure provides visiting

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Interaction

  • 7/27/2019 06 Design Patterns Visitor

    38/79

    accept(visitor)accept(visitor)

    anObjectStructureanObjectStructure elementAelementA elementBelementB visitovisito

    accept(visitor)accept(visitor)

    visit(elementAvisit(elementA))

    operationAoperationA()()

    accept(visitor)accept(visitor)

    visit(elementBvisit(elementB))

    operationBoperationB()()

    aClientaClient

    Internal iterator

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visiting Several Class Hierarchies

  • 7/27/2019 06 Design Patterns Visitor

    39/79

    g

    Visitor

    visit(ElementA ...)

    visit(ElementB...)visit(ElementC ...)

    visit(ElementD ...)

    BaseElement1

    accept(Visitor)

    ElementA ElementB

    BaseElement2

    accept(Visitor)

    ElementC ElementD

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Summary of Advantages

  • 7/27/2019 06 Design Patterns Visitor

    40/79

    + New operations are easy to add without changingElement classes (just add a new ConcreteVisitor)

    + Related behavior is gathered in a singleConcreteVisitor. Different ConcreteElements

    dont have to implement their part of a particular algorithm

    + Allows visiting across hierarchies: visited classes may notshare a common base class

    + Accumulating state: visitors can accumulate state as theyvisit each element, thus encapsulating the algorithm and

    all its data within the visitor

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Problems

  • 7/27/2019 06 Design Patterns Visitor

    41/79

    Adding new ConcreteElements is difficult each time a new ConcreteElement is added that

    needs to be visited by a visitor, a function must be added to

    the abstractVisitor class and allConcreteVisitors that need to visit the new

    ConcreteElement

    Software TechnologyGroupTU-Darmstadt | FB Informatik Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    42/79

    What if we dont want to support new elements in existing

    visitors?

    Sometimes data structures are extended, but its optional to

    process extensions

    Example: new kind of graphical element (e.g., charts) is added; wedont have to extend spell checking

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    43/79

    abstract class DocumentElement {

    abstract void accept(Visitor v);

    ...

    }

    children

    Document

    DocElement

    Character Graphic

    Row Column

    Group

    *

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    44/79

    DocElement

    void accept(Visitor v) {

    v.visit(this);

    }

    children

    Document

    Character Graphic

    Row Column

    Group

    *

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    45/79

    SpellChecker

    visi t( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    DocElement

    accept( Visitor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    46/79

    interface Visitor {void visit(Group elem) ;

    void visit(Charcter elem);

    void visit(Graphics elem);

    }

    class SpellChecker implements Visitor {String word;

    void visit(Group elem) {

    foreach(DocumentElement child : elem.childen)

    child.accept.this;

    }

    void visit(Charcter elem) { }

    void visit(Graphics elem) { /* ignore */ }

    }

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    47/79

    SpellChecker

    visi t( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    ChartVisitorvisit( Group )

    visit( Character )

    visit(Chart)

    ...

    DocElement

    accept( Visitor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    Chart

    accept( Visitor v )

    PrintVisitor

    visi t( Group )

    visit( Character )visit(Chart)

    ...

    void accept(Visitor visitor) {

    if(visitor instanceof ChartVisitor)

    ((ChartVisitor) visitor).visit(this);}

    Careful: Chart can only

    accept ChartVisitors!

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    48/79

    interface ChartVisitor extends Visitor{

    void visit(Char elem);

    }

    class PrintVisitor implements ChartVisitor {void visit(Group elem) { /* decend into group */ }

    void visit(Charcter elem) { /* print character */ }

    void visit(Graphics elem) { /* print graphics */ }

    void visit(Chart elem) { /* print chart */ }

    }

    interface Visitor {

    void visit(Group elem) ;void visit(Charcter elem);

    void visit(Graphics elem);

    }

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    49/79

    SpellChecker

    visi t( Group )

    visit( Character )

    ...

    Visitor

    visit( Group )

    visit( Character )

    ...

    ChartVisitorvisit( Group )

    visit( Character )

    visit(Chart)

    ...

    DocElement

    accept( Visitor v )

    Character

    accept( Visitor v )

    Group

    accept( Visitor v )

    Chart

    accept( Visitor v )

    ChartSpellChecker

    visit ( Group )

    visit( Character )visit(Chart)

    ...

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern Summary

  • 7/27/2019 06 Design Patterns Visitor

    50/79

    Without the visitor abstraction

    adding new functions (algorithms)to an object structure is difficult.

    With the visitor abstraction adding

    new elements to the objectstructure is difficult.

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Two Approaches to Structuring Software

  • 7/27/2019 06 Design Patterns Visitor

    51/79

    Spaghetti-CodeSpaghetti-Code

    Functional DecompositionFunctional Decomposition Object DecompositionObject Decomposition

    Form = data typeColor = functionality

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Functional Decomposition

  • 7/27/2019 06 Design Patterns Visitor

    52/79

    Advantagenew functionalityeasy to integrate

    Advantagenew functionalityeasy to integrate

    DisadvantageIntegrating new data typesrequires the modification

    of several functions

    DisadvantageIntegrating new data typesrequires the modification

    of several functions

    Form = data typeColor = functionality

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Object Decomposition

  • 7/27/2019 06 Design Patterns Visitor

    53/79

    AdvantageNew data typeseasy to integrate

    AdvantageNew data typeseasy to integrate

    Form = data type

    Color = functionality

    DisadvantageIntegrating new functionalityrequires modification of

    several classes

    DisadvantageIntegrating new functionalityrequires modification of

    several classes

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Adding New Elements

  • 7/27/2019 06 Design Patterns Visitor

    54/79

    With the visitor pattern, were applying functional

    decomposition

    Our goal was indeed to facilitate the introduction of

    new functionality!

    As a by-product we also get the disadvantages offunctional decomposition in our design

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Cyclic Dependencies

  • 7/27/2019 06 Design Patterns Visitor

    55/79

    Elementaccept(Visitor v)

    ElementA

    accept(Visitor v)ElementB

    accept(Visitor v)

    Visitor

    visit(ElementA)

    visit(ElementB)

    Visitor1

    visit(ElementA)

    visit(ElementB)

    Visitor2

    visit(ElementA)

    visit(ElementB)

    Software TechnologyGroupTU-Darmstadt | FB Informatik Visitor Pattern: Cyclic Dependencies

  • 7/27/2019 06 Design Patterns Visitor

    56/79

    Due to theVisitor-Element dependencycycle of the pattern, even clients ofElementmight need to be recompiled

    Adding a new Element type requires to:a) changeVisitor, which in turn requires

    b) Element to be recompiled since it depends

    uponVisitor, which in turnc) requires clients ofElement to be

    recompiled, including all existing derivatives

    ofElement and their using clients.

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Visitor Pattern: Partial Visiting NotSupported

  • 7/27/2019 06 Design Patterns Visitor

    57/79

    A method needs to be written for the cross productof allVisitor and Element classes

    In order to provide a common abstractVisitor

    interface to Element, every derivative ofElementneed to be addressed by every derivative ofVisitor even if this might not make sense or is

    not needed

    Cannot make use of the polymorphism in theElement hierarchy: accept() must be

    implemented in all subclasses

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Visitor Pattern: Partial Visiting notSupported

  • 7/27/2019 06 Design Patterns Visitor

    58/79

    Assume, we have a hierarchy ofModemclasses withone derivative for each manufacturer and we need to

    configure modems for different operating systems

    We dont want to put configuration functionality inModem, hence, we use the visitor pattern

    there is no end to such functions

    dont wantModemto recognize any variation on

    operating systems

    Example

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Visitor Pattern: Partial Visiting notSupported

  • 7/27/2019 06 Design Patterns Visitor

    59/79

    Modem

    accept( Visitor v )

    HayesModemaccept( Visitor v )

    ZoomModem

    accept( Visitor v )

    Visitor

    visit(HayesModem)

    visit(ZoomModem)

    Configure forUNIX

    Configure forDOS

    partial visiting not supported

    need to implement visit(HayesModem) in the visitor

    that performs UNIX configuration, even if we never useHayes modems with UNIX machines

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Visitor Pattern: Partial Visiting notSupported

  • 7/27/2019 06 Design Patterns Visitor

    60/79

    A solution would be to use a hierarchy of visitors

    Like in the "Chart Example"

    This again couples structure element to kind of

    functionality available for it

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism

  • 7/27/2019 06 Design Patterns Visitor

    61/79

    Querying the intersection of a

    shape by another anonymous

    shape is common in GUI

    programming.

    Each concrete shape type has its own definition of

    what it means to have an intersection with another

    shape

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism

  • 7/27/2019 06 Design Patterns Visitor

    62/79

    " let intersect(Shape) be a virtual method inShape - the abstract base class of all shapes.

    " concrete Shape subclasses must implementintersect(Shape) specifically

    " we call this left-handed (singular) polymorphism.

    "Object-oriented languagesallow us to implement anintersection operation

    specifically for each shapetype in a straightforward way:

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism

  • 7/27/2019 06 Design Patterns Visitor

    63/79

    ...

    if (s1.intersect(s2))

    ...

    We get boolean Rectangle.intersect( ??? )

    Shape s1 = new Rectangle();

    Shape s2 = new Triangle();

    Shape s3 = new Circle();

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism

  • 7/27/2019 06 Design Patterns Visitor

    64/79

    The problem of intersecting two anonymous shapes is agenuine challenge.

    Assume that there must be a special intersect()

    function for each combination of two shape types.

    The operation intersect(Shape) in Shape will only

    solve the identity of the left-hand object but will leave the

    identity of the right-hand object unsolved.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    65/79

    Double dispatch In addition to the two-shape intersect operation,

    intersect(Shape), declare in Shape an operation

    for each possible concrete parameter type,intersect(Circle), intersect(Rectangle),

    etc.

    Redefinitions ofintersect(Shape) in concrete

    subclasses ofShape call the specific intersect

    function of the parameter object with the receiver asargument.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    66/79

    Circle

    Shape

    intersect(Shape s)

    intersect(Circle c)

    intersect(Rectangle r)intersect(Triangle t)

    Rectangle Triangle

    intersect(Shape s)

    intersect(Circle c)

    intersect(Rectangle r)intersect(Triangle t)

    intersect(Shape s)

    intersect(Circle c)

    intersect(Rectangle r)intersect(Triangle t)

    intersect(Shape s)

    intersect(Circle c)

    intersect(Rectangle r)

    intersect(Triangle t)

    // code for deciding whether// a Triangle (receiver)// and a Rectangle (parameter)

    // intersect

    s.intersect(this);

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    67/79

    c

    Shape c = new Circle();Shape r = new Rectangle();

    c.intersect(r);

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    68/79

    r

    Shape c = new Circle();Shape r = new Rectangle();

    c.intersect(r);

    c

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    69/79

    r

    Shape c = new Circle();Shape r = new Rectangle();

    c.intersect(r);

    c

    intersect(Shape r)

    First dispatch: on the dynamic type of the receiverCircle.intersect(Shape) chosen at runtime

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    70/79

    r

    Shape c = new Circle();Shape r = new Rectangle();

    c.intersect(r);

    c

    Circle.intersect(Shape r) {

    r.intersect(this);

    }

    Compiler knew that this isa Circle. It has changedthe call to: "find a method

    for intersect(Circle)based on the dynamic typeofr and call it with c as aparameter"

    intersect(Circle c)

    Second dispatch: based on the dynamic type of the parameter of

    the original call (rhs)Rectangle.intersect(Circle) chosen for execution at runtime

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    71/79

    r

    Shape c = new Circle();Shape r = new Rectangle();

    c.intersect(r);

    c

    Circle.intersect(Shape r) {r.intersect(this);

    }

    intersect(Circle c)

    Rectangle.intersect(Circle c) {// test whether the Circle c and

    // the rectangle "this" intersect }

    Finally we get the code that is specific for

    the receiver type / parameter type pair.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Double

    Dispatch

  • 7/27/2019 06 Design Patterns Visitor

    72/79

    The double dispatch approach is efficient and worksin fixed time.

    However, it compromises the semantic hierarchyconcept. It results in an inheritance tree where each

    derivative is aware of each other's existence.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Visitor

  • 7/27/2019 06 Design Patterns Visitor

    73/79

    The cross-reference in each shape derivative toeach other shape derivative may be eliminatedby removing the intersect functions to visitors.

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Visitor

  • 7/27/2019 06 Design Patterns Visitor

    74/79

    ShapeVisitor v =intersector();

    return rhs.accept(v);

    Shapeintersect(Shape rhs)

    boolean accept(ShapeVisitor v)ShapeVisitor intersector()

    Triangle

    boolean accept(ShapeVisitor v)ShapeVisitor intersector()

    Circle

    boolean accept(ShapeVisitor v)ShapeVisitor intersector()

    return new CircleIntersect(this);

    return new TriangleIntersect(this);

    return v.visit(this);

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Visitor

  • 7/27/2019 06 Design Patterns Visitor

    75/79

    ShapeVisitor

    boolean visit (Circle)boolean visit (Triangle)

    CircleIntersect

    boolean visit (Circle)boolean visit (Triangle)

    TriangleIntersect

    boolean visit (Circle)boolean visit (Triangle)

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Visitor

  • 7/27/2019 06 Design Patterns Visitor

    76/79

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Multi-

    Methods

  • 7/27/2019 06 Design Patterns Visitor

    77/79

    Multi-methods: Manage a registry ofintersect() functions

    taking two shapes.

    Each function is registered with two class

    identifiers.

    Given two class identifiers, the general

    intersect() function looks up the handler in theregistry.

    Software TechnologyGroupTU-Darmstadt | FB Informatik

    Double Polymorphism with Multi-Methods

  • 7/27/2019 06 Design Patterns Visitor

    78/79

    Circle Rectangle

    Shape

    intersect(Shape s)

    ...

    Triangle

    static multiMethCircle/Triangle

    Circle/

    Rectangle

    Multi-methods

    String otherClass = s.getClass().getName();

    String thisClass = getClass().getName();

    Method meth = (Method) multiMeth.elementAt(thisClass, otherClass);

    Object[] args = new Object[1];args[0] = s;

    Object res = meth.invoke(this, args);

    boolean result = ((Boolean) res)getBooleanValue();

    return result

    Software TechnologyGroupTU-Darmstadt | FB Informatik Double Polymorphism with Multi-

    Methods

  • 7/27/2019 06 Design Patterns Visitor

    79/79

    The multi-method solution is expensive.

    It also involves extensive application of down casting

    There are object-oriented programming languages that

    directly support multiple dispatch

    CLOS (dynamically typed, LISP derivative),

    CECIL (statically typed),

    MultiJava (statically typed, Java dialect)

    Will use MultiJava in lab later this term.


Recommended