0

So the decorator pattern allows you to add behaviour to a class dynamically, right? However, the decorator has to be inherited from the base class of the class getting the behaviour or must implement one of its interfaces. Indeed, all the examples I can recall have had one exposed function so applying a decorator works well however what if you want to make a decorator to add behaviour such as logging to various classes that no not have the same interface- it won't work. Am I missing something here? Is this a hint that all classes that I would want to log SHOULD be wrapped in the same interface, like a command or something?

For example

class A { whatever(); idontknow(); } class B { bananas(); } 

I can't make a decorator to log the calls of the functions in these classes because they are different.

2 Answers 2

2

I believe that you might have misunderstandood the decorator pattern, and from your explanation of the problem, it seems that you actually need something else: you need to implement a cross-cutting concern - some common functionality which can be applied across completely unrelated behavior. E.g. you want to wrap logging around unrelated functions.

This is known as aspect oriented programming, or AOP for short.

There are tools which allow you to intercept calls to the methods, and augment them with the desired behavior, i.e. you can add logging around method calls, or ensure that the user has sufficient rights to execute the call, etc. Some of these tools in .NET implement this by modifying the IL, while others dynamically wrap the types in runtime.

I have provided an example in this answer and here too.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks but in that example the decorator still has to implement a specific method doesn't it? After thinking about your example there's probably a way to make a decorator using reflection (you can do anything with reflection) that does not have to implement a specific method but that seems pretty inelegant and anti-design patterny...
The decorator pattern is a well defined concept: augmenting the functionality by wrapping an object, while providing the same interface to the client: stackoverflow.com/questions/12379848/…. What you are describing is not the decorator pattern (which doesn't make it less valuable). With the interception example you don't need to reimplement the method. You implement one method which is then applied around all other methods marked with the attribute. Please check the code samples.
In that example the interceptors have to implement IService or it doesn't work... but I think I get the idea- in an actual IoC framework it would use reflection trickery to apply the interceptor to any method with the custom attribute and wouldn't involve polymorphism at all.
that's because the example uses a form of decorator, as noted in the answer, not the proper AOP - hence 'Poor man's AOP'. Follow the second link in that answer for real AOP implementation, or google AOP in .NET. Also, there is an example here: stackoverflow.com/questions/15323009/…
1

It is only necessary that Decorators be able to 'mimic' the base class like this:

Class ADecorator : A { ADecorator(A a) { /* etc */ } void whatever(); void idontknow(); } class BDecorator1 : B { BDecorator1(B b) { /* etc */ } void bananas(); } class BDecorator2 : B { BDecorator2(B b) { /* etc */ } void bananas(); } 

and accept an instance of the base class in their constructor.

5 Comments

Right, but if I have one behaviour I want to add to two different classes I have to make two types of decorators don't I? If that is the case it seems like I could end up writing a LOT of code when I could certainly find an easier way to include the behaviour with some degree of reusability.
If refactoring the old classes is an option, take it; the reduction in overall code-entropy is almost certainly worth it in a re-design like this. However, if you do not have the option to refactor old classes, you need to make do until you can.
What do you mean? The classes simply have different interfaces, how do I refactor them to make it work?
ALL of their non-common attributes could be refactored as decorators, leaving only the common attributes and any desired decorator support.
Why don't you do some homework, and call back with specific issues encountered in that endeavour.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.