Search code examples
c#design-patternsdecoratorcomposition

Decorator pattern: enhanced design?


I'm reading and example provided in "Head first design patterns book" about decoration pattern.

I have noticed 2 things:

  1. if you will need to remove a decorator from the stack of the wrapped decorators, you will have to iterate one by one through the component reference, which is O(n) complexity.
  2. Conceptually I find it wrong to wrap (encapsulate) the base component in to the decorator object. It should be reversed; the component object should encapsulate the decorating objects.

I'm new to design patterns, and there is high probability that I'm wrong. Please explain to me what is specifically wrong with the way I think so I can learn.

I have created a different design, which solves the problems that I have mentioned. Maybe they add new problems; please feel free to point out the issues.

Here is the UML Diagram of the suggestion:

UML Diagram of the suggestion

Basically what I did is that I have created a dictionary in the Component class which saves which decorators have been added, and made the Decorator abstract class not inherit from the component yet from Interface (so the component abstract class).

In this way, we can remove any decoration we want with O(1) complexity, and it is more logically constructed in the way that the component wraps the decorator, not the vice versa.

I understand that maybe I didn't noticed some advantage of the original Decorator pattern design. Please advice me.

Here is my code url.

Edit:

An example of when a customer will need to remove a decorator:

say for example the customer is choosing the condiments, he is adding whip, removing caramel, see each time how the total price vary, based on what the client is choosing to be added as a decorator.


Solution

    1. if you will need to remove a decorator from the stack of the wrapped decorators, you will have to iterate one by one through the component reference, which is O(n) complexity.

    It's true that removing decorators is theoretically more complex when they're wrapped. However, you need to consider what is a likely n. I'm going to guess for the decorator pattern as it was proposed, there are probably a small (max(n) == 20) iterators. Iterating over that many would not be a practical problem.

    1. Conceptually I find it wrong to wrap (encapsulate) the base component in to the decorator object. It should be reversed; the component object should encapsulate the decorating objects.

    The Decorator pattern seeks to add functionality (via concrete decorators) without having to modify the component class. In some cases, a Component can't be changed (e.g., it comes from a standard library). With the approach you propose, the Component would have to be modified to encapsulate its decorators. This is not the intention of Decorator.

    In the original GoF book, the design patterns have clear definitions of the problem they solve, and the consequences (which are not all positive!) of the design pattern. In line with your complexity point (removing decorators), the authors mentioned this consequence:

    1. Lots of little objects. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug.