[ACCEPTED]-Difference between decorator design pattern and visitor design pattern-visitor

Accepted answer
Score: 34

Well, they are actually as different as 14 they can be!

You use Decorator when you want to enhance 13 existing object with some new, more-or-less 12 transparent functionality like validation 11 or caching. See example here: Should I extend ArrayList to add attributes that isn't null?

Visitor on the other 10 hand is used when you have a hierarchy of 9 classes and want to run different method 8 based on concrete type but avoiding instanceof or 7 typeof operators. See real-life example: Is This Use of the "instanceof" Operator Considered Bad Design?

Decorator 6 works on an object, Visitor works on composite 5 structure,

Visitor works on an inheritance hierarchy, Composite is 4 a different GoF design pattern.

Decorator 3 is Structural design pattern, visitor is 2 Behavioral design pattern.

True, but it doesn't 1 really help in understanding how they work?

See also

Score: 13

Design patterns are not meant to be categorized 3 by the implementation differences but by 2 when you should use one or the other one.

They 1 serve for absolutely different purposes:

  • you will use decorator when you want to dynamically enrich the functionality of objects by providing single elements that decorate other objects so that they do actually add some behavior to them (in fact it is a structural pattern in the sense that it alters the structure of the objects you are woking with)
  • you will use visitor when you want to separate an algorithm from the objects it is used with. What you do is that you have this visitor which is passed to a multitude of different objects, usually a hierarchy, (they are said to accept the visitor), this visitor does specific operations according to the type of objects it is visiting in the specific moment. In this way you can have your visitor do whatever it wants with the specific objects without the need to specify these operations in the objects itself (that's why it is behavioral). It's a sort of having abstract methods that are not defined in the object itself.
Score: 9

They both "add functionality" to an existing 30 object, without modifying the original class. The 29 difference is:

With decorator You add functionality that 28 wraps basic functionality that this object 27 has (e.g. in addition to perform some basic 26 action also write it to log, in addition 25 to write a file to disk also encrypt it). This 24 also allows us to create different combinations 23 of decorators without subclassing each possible 22 scenario.

With visitor You add a completely new behavior 21 that you don't want to define as part of 20 the basic component class itself (not even 19 as a wrapper to basic functionality), for 18 example because of single responsibility 17 principle, open close principle etc. It's 16 especially useful when that behavior will 15 be different between different subclasses 14 of the same type (if there isn't any complex 13 structure of subclasses but just one class 12 you could just create a new class and include 11 the original class via composition and still 10 achieve the goal of not affecting or modifying 9 the original class). That way you can avoid 8 code like if (a is ConcreteClass1) {...} else if (a is ConcreterClass2) {...} without writing virtual methods.

As 7 a result of this difference, with decorator 6 the client code calls the same method which 5 is defined on the interface of the basic 4 component class, it's just "decorated" with 3 extra functionality now, while with visitor 2 the client calls some general "accept" method 1 and sends a visitor to it.

Score: 4

The way I interpret it, visitors represent 18 actions that we may want to take on or with 17 an object, but that are not necessarily 16 inherent to an object, and are rather horizontal 15 in relationship. For example, I could "make 14 a marketing pitch" for a car, but I wouldn't 13 program a car object to have a "createMarketingPitch" function 12 because that would be a slippery slope towards 11 creating many many functions on my car object.

On 10 the other hand, a decorator is a pattern 9 that layers functionality on top of an existing 8 object, a vertical relationship that modifies 7 how the object behaves when its normal functions 6 are called. Additionally, whereas a visitor 5 is coded to work with a class of objects, decorators 4 can be assigned to specific instances of 3 the object so that different instances of 2 the same type behave differently than each 1 other.

Score: 3

I like to think that decorator allows to 16 avoid inheriting and then extending the 15 class as is the general principle of OOP 14 to prefer aggregation over inheritance, although 13 you do inherit in a way. Here is a overly 12 simplistic example

abstract class Chef{
  public abstract void Prepare();
}

class CookieMaker:Chef{         //Concrete class
   public override void Prepare()
    {
        //Bake in Oven
     }
 }

  // Decorator class
 // This chef adds chocolate topping to everything
 class ChocoChef:Chef{  

     public ChocoChef(Chef mychef)
     {
        this.chef = mychef; 
     }

     public override void Prepare()
     {
           // Add chocolate topping first
           chef.Prepare()
     } 
 }

I'v cut short some details 11 for the sake of space. For example, you 10 could abstract out a chef which adds any 9 kind of topping and ChocoChef then becomes 8 its concrete class. Now ChocoChef always 7 adds chocolate toppings no matter what you're 6 preparing. So now you can have either chocolate 5 cookies or chocolate cake by passing the 4 correponding Chef to its constructor. The 3 visitor on the other hand acts on objects 2 and decides to do something based on the 1 object that it is visiting.

class Student{
     // Different visitors visit each student object using this method
     // like prize distributor or uniform inspector
     public Accept(IVisitor v)
     {
         v.Visit(this)
     }
}

 // Visitor visits all student OBJECTS
class PrizeDistributor:IVisitor{
     public override void Visit(Student s)
     {
           //  if(s has scored 100)
           // Award prize to s
     }
}
Score: 1

Decorator

The Decorator pattern can be used to extend (decorate) the 13 functionality of a certain object statically, or 12 in some cases at run-time, independently 11 of other instances of the same class, provided 10 some groundwork is done at design time

When to Use Decorator pattern?

  1. Object responsibilities and behaviours should be dynamically added/removed
  2. Concrete implementations should be decoupled from responsibilities and behaviours
  3. When sub - classing is too costly to dynamically add/remove responsibilities

Related 9 post:

When to Use the Decorator Pattern?

Visitor:

Visitor design pattern is a way of separating 8 an algorithm from an object structure on 7 which it operates. A practical result of 6 this separation is the ability to add new 5 operations to existing object structures 4 without modifying those structures. It is 3 one way to follow the open/closed principle.

When to use Visitor pattern?

  1. Similar operations have to be performed on objects of different types grouped in a structure
  2. You need to execute many distinct and unrelated operations. It separates Operation from objects Structure
  3. New operations have to be added without change in object structure
  4. Gather related operations into a single class rather than force you to change or derive classes
  5. Add functions to class libraries for which you either do not have the source or cannot change the source

Related 2 post:

When should I use the Visitor Design Pattern?

Useful links:

sourcemaking decorator article

oodesign visitor 1 article

sourcemaking visitor article

Score: 0

The way i think of decorator pattern is 15 when i want to add functionality to an object 14 at runtime. I can add behavior to an object 13 while the program is running by wrapping 12 the object in a decorator class which can 11 extend its methods.

For the visitor pattern 10 i like it when i have to do an operation 9 on "a set" of objects of the same type and 8 collect the information. Lets say i have 7 10 concrete classes of vegetables and i 6 want to know the total price for all 10. i 5 can use the visitor pattern to "visit" each 4 vegetable object and at the end of the iteration 3 i'd have the total price. Of course you 2 can also use the pattern as a way to decouple 1 some operation from the object(s).

Score: 0

Yes, they both add some functionality to 43 the existing system at run-time and try 42 to be less reactive (in a good meaning) to 41 dynamic changes, but with some differences.

Visitor 40 is primarily to respect OCP (and sometimes 39 to SRP), to make the system more flexible. You 38 can add whatever Visitor you can as your 37 program evolves without changing the existing 36 system. However, you need to design the 35 system in such a way beforehand. You can't add a new 34 Visitor class (or pattern) to already running 33 system and expect it to work without re-compiling, re-testing 32 or whatsoever.

On the other hand, you can 31 use Decorator to enrich the existing system functionality by 30 wrapping the abstract base class (that you 29 already have) in a Decorator and provide 28 the enriched feature of yours as a separate 27 object so you can you can create as you 26 need. Moreover, semantically, Decorator 25 rather refers to appearance of sth.

Which 24 one to prefer? IMO, answering this might 23 be more helpful. For me, I don't like the 22 Decorator's way of use the base class. It 21 both uses inheritance and aggregation. If 20 you need to change this (wrapee) class, you 19 end up with re-compiling entire hierarchy/module. But 18 it's handy since and you can change the 17 behavior after design time. On the other hand, in Visitor 16 pattern, I don't like the idea of knowing 15 each concrete types in the Visitor implementation. When 14 you add a new base class type, you also 13 need to go and change the Visitor class 12 to add it. But it's useful when you need 11 to inject a code to the existing system without 10 altering the structure or you need to separate 9 concerns in a class (Single-User Resp).

Finally, what 8 makes Visitor better than regular inheritance? Depends. Using 7 inheritance you will be more dependent to 6 interface signature. Using Visitor makes 5 your Visitor class dependent to concrete 4 classes. Not to mention you add more behaviours 3 using visitor without changing existing 2 module signature instead of implementing 1 new interfaces in the existing class.

More Related questions