Adding functionalities without changing existing code in Java: practical example

The decorator design pattern allows to add behaviour to an object without changing it, by implementing the behaviour in a new object that “wraps” the original one without extending it. Clear advantages are keeping the logic in separate classes, being able to compose them and being able to unit-test them in details.

Let’s take for example a basic URL download functionality. I just want to download an URL from a server and get the content, but I also want to cache the result, and also have a…