With all of the substitution patterns, the principle is that the proxied target doesn’t need to be aware of the proxying object. That’s pretty achievable if what you’re trying to do is provide a local proxy to a remote object. However, when you’re using a decorator, things get a bit trickier. Welcome to the “leaking this” problem.
To start with an easy example, what if the target does this:
What do you do? Well, it’s not obvious, but typically you’ll get the decorator to return itself. This case is relatively easy to spot. But how about if it does this
Here you can’t intercept the call at all. Maybe you didn’t want to, but this is the case in which inheritance can actually be more useful than composition. But there’s an even worse case:
return new SomeOtherObject(this);
Okay, well your decorator can give SomeOtherObject a decorator as well, and often that’s what you wanted to do. But sometimes you actually wanted SomeOtherObject to take a dependency on the decorator, and that can’t be achieved. Using a factory doesn’t help, since it’s typically a constructor dependency and as such unaware of the decorator.*
It just gets worse. What if your target raises an event? You’re going to have to make sure the sender points to the decorator. The target could stick itself into a global variable (ugly, but possible). So what’s the solution? Here’s the thing: there isn’t one. There are solutions for specific cases, but there’s no general way of replacing an object with a decorated version. Sometimes, you’ve just got to redesign your target object to make sure you get the behaviour you want.
Why Isn’t This a Problem For Remote Proxies?
You might be thinking “but I’ve been using Remoting/WCF/RMI for years and I’ve never had a problem”. And you’d be right. The thing is: proxies don’t change behaviour, so you never encounter a position in which using the unproxied version would cause an issue. The original object stays on the server, the proxy stays on the client. If you take a look at the examples above, it’s really easy to answer the question “What should the proxy do?”
If you think that it’s painful to deal with hand-written decorators, wait until you try to build a framework for decorators. Castle’s InterfaceProxyWithTarget and InterfaceProxyWithTargetInterface** methods are exactly that: general ways of writing decorators. Anyone who uses DynamicProxy runs into the problem sooner or later. The knee jerk reaction is that there’s something wrong with DynamicProxy. Later on you realize it’s a limitation of the programming language: there’s simply no expressing what you actually wanted to achieve.
*You could pass the factory in as a function parameter, but you’d typically have to redesign your target to achieve this.