Simple explanation of Decorator Pattern

Situation: You’re Building a File Uploader

You’ve written a class called FileUploader. Its job is simple: take a file and upload it to some server.

Everything works fine. Life is good.

Now Requirements Change (as they always do)

  1. PM says: “Can we log every file upload?”
  2. Then QA says: “Hey, add virus scanning before upload.”
  3. Then Legal says: “Encrypt files before uploading.”

You think: “Okay, lemme just keep adding code inside FileUploader…” But wait -

Here’s the Risk

  • Your FileUploader class is doing too many things now.
  • Every change can accidentally break existing upload logic.
  • Testing becomes painful. You now need to test 10 things for one upload.
  • Worse, someone tomorrow might say “skip encryption in staging” or “add compression too.”

You’re now stuck in if-else hell and code soup.

How Decorator Saves You

Instead of stuffing all logic into FileUploader, you:

  1. Keep FileUploader clean - it only uploads.
  2. You wrap it in a LoggerDecorator - adds logging before upload.
  3. Then wrap that in a VirusScannerDecorator - scans before passing the file down.
  4. Then an EncryptorDecorator - encrypts before handing it to the next layer.

Each of these decorators looks like a FileUploader from the outside, but they’re just adding layers of behavior, one at a time.

Now What’s the Benefit?

  • You can mix-match behavior: log + scan + encrypt OR just log + encrypt.
  • You can add new features without ever touching core logic.
  • Unit tests are easy: test each decorator independently.
  • No risk of breaking FileUploader itself - zero regression risk.