Reputation: 979
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.
Upvotes: 0
Views: 724
Reputation: 14581
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.
Upvotes: 2
Reputation: 11883
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.
Upvotes: 1