The decorator pattern is a design pattern that allows behaviour to be added to an existing object dynamically.
I don’t have a lot to say about this pattern.
The decorator pattern is still just as useful if not more so as the time it was initially announced. It forms a core part of many critical function of your day to day software.
The most obvious example is the notion of Stream, where you often decorate a stream (Buffered Stream, Compressing Stream, etc). This example is valid not just for the .NET framework, I can’t think of a single major framework that doesn’t use the Stream abstraction for its IO.
Then again, the cautionary side, people try to use it in… strange ways:
Something like this, for example, is a pretty bad way of doing things. It assumes a very fixed model of looking at the universe, which is just not true. Decorator works best when you have just a single I/O channel. When you have multiple inputs & outputs, decorating something becomes much harder.
In particular, implementing business logic like the one above in decorators make it very hard to figure out why things are happening. In particular, CachingDecorator is something that you want to avoid (better to use infrastructure or a auto caching proxy, instead).
Recommendation: It is a very useful pattern, and should be used when you actually have one input / output channel, because that is a great way to allow to dynamically compose the way we apply processing to it.