I had some engaging conversation with my co-worker and we've discussed the "proper way" of Decorator Pattern usage. Unfortunately I couldn't find any confirmation of my assumptions and it's the reason of how my question have begotten.
Let see:
- If we have
HandlerInterface
and alsoHandlerImpl
andDecoratorImpl
which both implements that interface, it's a decorator pattern? - But if our
HandlerInterface
contains many methods, and we want to decorate only some methods, we could use alsoAbstractDecorator
which implementsHandlerInterface
contract and some of its methods by default? - But what if we have only one implementation of
HandlerInterface
? May it become redundant in some use cases? Which could mean, we don't need an interface only for this and we could just replace usages ofHandlerInterface
withHandlerImpl
?. - And then our
AbstractDecorator
will not implementHandlerInterface
but extendHandlerImpl
instead. And if we would've done this. Why couldn't we just removeAbstractDecorator
and useHandlerImpl
directly in ourDecoratorImpl
as a contract? Maybe it's a bit far from the standard design, but as I understand, It's still a decorator pattern but after some modifications.
So, Is it a good way of thinking? Or maybe I'm missing something? Let me know. Thanks in advance.
1 Answer 1
No. There is no call for an AbstractDecorator
. Decorators typically use composition and delegation anyway.
If you're a fan of UML these diagrams might help.
https://en.wikipedia.org/wiki/Decorator_pattern
See? No abstract decorator. Component
might be abstract but it has no idea the decorator exists. The Decorator
both implements the Component
interface and accepts a Component
. That way it can pretend to be one and pass on what it's told to do to the Component
it holds. Why? So it doesn't have to do that work itself. The Decorator
can pretend to be both the Component
and the Client
while making them still do their work. This way all it has to do is add whatever behavior it was created to add.
But let's try an example from the real world.
pictures of gas pumps with and without credit card skimmer attached
You're looking at two gas pump credit card readers. Except the one on the left has a skimmer attached. Use either one and you can fuel your car. But the one on the left has added the behavior of sharing your credit card info with criminals. That's a decorator. Everything looks the same from the outside but new behavior has been added.
Decorators are used when you want to add new behavior without upsetting the rest of the system. The idea is to slip them in unnoticed. It's very powerful. Please don't use it for evil.
See also: man in the middle attack
-
Interesting choice for an example. Previous career? :)Robert Harvey– Robert Harvey2020年12月07日 18:53:27 +00:00Commented Dec 7, 2020 at 18:53
-
That real world example is actually amazing. And those diagrams are really interesting, and clarify things a bit, but I have one doubt. On Wikipedia site (actually your reference), has been said - "In the above UML class diagram, the abstract Decorator class maintains a reference (component) to the decorated object". So, I can use that abstract which implements Component, make a constructor which takes exactly that interface, and pre implement some of it's methods (by passing reference to the inherited object), and then, In my Decorator instances, decorate only methods I want. Right?Maciej Król– Maciej Król2020年12月07日 23:03:34 +00:00Commented Dec 7, 2020 at 23:03