• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Query regarding Visitor design pattern

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Everyone,
I am in the process of understanding the Visitor design pattern. My understanding is that somewhere this pattern creates a monolithic class with various functions.
If even 1 of the functions changes, then either a new class has to be created (just to change a function and copying the rest of the functions as it is) or one can edit the current function thereby violating open/close principle.

Let me share an example.



below is one of the classes that implement the above interface



Now suppose Necessity's implementation changes, either one has to create another implementation, copying the rest of the code, to just change Necessity or one has to manually change the visit method (used by Necessity), thereby violating open/close principle.

Is this violating the interface segregation principle?  Can we improve or change anything in this? Thanks in advance.
 
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What do you mean by "Necessity's implementation changes"? And why does that mean one has to change the implementation of the visitor? Maybe it's best if you give a concrete example.
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
1. True, for every new type of taxable item you need to visit, you'll need to add a new overloaded version of the visit() method. That's the disadvantage of the Visitor pattern.
2. Re "this patterns creates a monolithic class with various functions" -- first of all, the pattern doesn't create anything. Maybe you meant "... this pattern results in a monolithic class with potentially many overloaded versions of the visit() method" -- this is more accurate and is in line with #1 above.
3. The "visit" method doesn't always need to be literally named visit(). In this case, I would probably name it "getTaxFor()" or something that more clearly expresses what it's doing in the language of the domain. The name "visit()" as documented in the pattern is just a generalization.
4. Your implementation has smells.
4a. This is smelly: return Double.parseDouble(df.format(. . .)); -- why do this here? Why even do it at all?
4b. The TaxVisitor is also a little smelly to me. Seems like this is more appropriately called something like TaxCalculator. If you really want to retain the "Visitor" part of the name (which like the "visit" name is really not a requirement), I'd name it TaxableItemVisitor instead but that's still not a name that clearly expresses what the visitor does.
5. Your problem does not appear to be something where the Visitor pattern would be appropriately applied.

You should understand the context in which a pattern is meant to be applied. If you apply a pattern in a context that is inconsistent with the intended purpose, you run the risk of turning it into an anti-pattern instead.

This is a pretty good description of the appropriate context for Visitor (from https://sourcemaking.com/design_patterns/visitor)

Many distinct and unrelated operations need to be performed on node objects in a heterogeneous aggregate structure. You want to avoid "polluting" the node classes with these operations. And, you don't want to have to query the type of each node and cast the pointer to the correct type before performing the desired operation.



 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic