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)
- PM says: “Can we log every file upload?”
- Then QA says: “Hey, add virus scanning before upload.”
- 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:
- Keep
FileUploader
clean - it only uploads. - You wrap it in a
LoggerDecorator
- adds logging before upload. - Then wrap that in a
VirusScannerDecorator
- scans before passing the file down. - 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.