Decorator Pattern and AOP considered equivalent
Every time I have looked into doing or learning about aspect-oriented programming, I’d be drowned in an obfuscated sea of specialty vocabulary (aspects, advice, pointcuts) and reflective black magic. It would turn me off. I always prefer to learn things the hard way. That way, you truly understand what is happening under the hood.
This isn’t to say that I haven’t understood AOP. I get it: there are certain cross-cutting concerns, the most typical example being logging, and objects throughout your system are often polluted with calls to a logger in addition to performing their normal function. This is rightly said to violate the Single Responsibility Principle. And any friend of the SRP is a friend of me.

So the idea is to extract these calls into an “aspect” and let the other objects focus on their work. See, the idea is not foreign, but its execution was because there are no examples anywhere that don’t involve reflective meta-magic. I want to know the basics!
Then today, a flash of Tylenol-inspired vision hit me. Typically you want something to happen, say, before a method executes and afterwards as well. Every AOP framework worth its stones, like AspectJ or Spring’s AOP, magically intercepts a method call and invokes the right parts of an aspect at the right moments.
Then I started remembering the design patterns training I took last year by Ken Pugh. There was an exercise that included logging, and it was demonstrating the use of the Decorator pattern.
Of course.
AOP is just a glorified decorator.
Allow me to explain. Here is the target object:
interface A
{
void foo();
int bar();
}
Here is the aspect, which is logging:
interface Logger
{
void logError(...);
void logInfo(...);
}
For each method in A, I want to log information before and after the method call. Here is the decorated A, called LoggedA:
class LoggedA implements A
{
private A target;
private Logger aspect;
void foo()
{
aspect.logInfo(...);
target.foo();
aspect.logInfo(...);
}
int bar()
{
aspect.logInfo(...);
int returnValue = target.bar();
aspect.logInfo(...);
return returnValue;
}
}
And this clearly necessitates a (not pictured) factory for the A object to return decorated or undecorated instances. And the example extends beyond intercepting method calls. Using the Decorator pattern, you can perform actions before or after exceptions are thrown, for example.
This is the idea behind AOP. This is similar to the epiphany you have when you realize that closures and objects are the same.
Why stop there? We can refactor a little bit:
class LoggedA implements A
{
private A target;
private Logger aspect;
Object logAndInvoke(String method, Object[] args)
{
aspect.logInfo(...);
Object returnValue = reflectivelyCall(method);
aspect.logInfo(...);
return returnValue;
}
void foo()
{
logAndInvoke("foo", null);
}
int bar()
{
return (int)logAndInvoke("bar", null);
}
}
And then what happens when I want to add another object to the mix?
interface B
{
int doSomething(String x, String y);
}
class LoggedObject implements A, B
{
private Object target;
private Logger aspect;
Object logAndInvoke(String method, Object[] args)
{
aspect.logInfo(...);
Object returnValue = reflectivelyCall(method);
aspect.logInfo(...);
return returnValue;
}
void foo()
{
logAndInvoke("foo", null);
}
int bar()
{
return (int)logAndInvoke("bar", null);
}
int doSomething(String x, String y)
{
return (int)logAndInvoke("doSomething", new Object[] { x, y });
}
}
It’s true that LoggedObject is becoming a God object. You could just as easily write separate classes for each type of logged object. The point here was to demonstrate how you could, I think, start with a home-brewed solution and gradually work your way up to the world’s worst AOP framework.
Let’s make this even more general:
interface Aspect
{
void preInvoke(...);
void postInvoke(...);
void beforeThrow(...);
}
class LoggedObject implements A, B
{
private Object target;
private Aspect aspect;
Object invoke(String method, Object[] args)
{
aspect.preInvoke(...);
Object returnValue = null;
try
{
returnValue = reflectivelyCall(method);
}
catch(Exception ex)
{
aspect.beforeThrow(...);
throw ex;
}
aspect.postInvoke(...);
return returnValue;
}
void foo()
{
invoke("foo", null);
}
int bar()
{
return (int)invoke("bar", null);
}
int doSomething(String x, String y)
{
return (int)invoke("doSomething", new Object[] { x, y });
}
}
There are questions I intentionally leave unaddressed with this code snippet: who injects the Aspect here? If that Aspect, let’s say, Logger, needs data passed to it, who passes it and how is it passed?
There are viable options, but they all lead you to start writing a container or a manager of some sort to manage wiring all of this together and passing the necessary data around, and hello AOP framework.
If you’ve ever decorated an object, you were either doing AOP or were close to it. That ought to knock those sophisticated AOP frameworks down a few notches. I’m on to you.
![]() |
Announcer: You’re reading the EIP web-ring. |

October 5, 2009 at 11:41 am
A very nice approach to understand AOP. I personally find AOP not so difficult to understand. Yes, it requires some learning, but once you get the hang of it, it’s quite easy and neat.
October 5, 2009 at 6:39 pm
Right, the idea isn’t difficult. Going from idea to how it works can be disorienting when you have to have faith in intermediate compilers and other bytecode manipulations. I like to know how stuff works. I think the best way to do that is to implement a scaled-down version of a grander idea.; e.g. many CS curricula require students to write a compiler.
October 28, 2010 at 7:02 am
I read couple of articles on AOP and i was trying to associate it with Decorator pattern. Your article is good.