Sunday, April 17, 2016

Decorator Pattern

A summary of the Decorator design pattern consisting of my notes from Head First Design Patterns and various web resources.

Description


The decorator pattern is built on an important design principal. Classes should be open for extension but closed for modification. We don’t want to constantly be updating existing code, instead we want our design to be flexible and resilient to change.

So the decorator pattern is an alternative way to add functionality w/o subclassing. 

Actually that is not completely true. The decorator does indeed use subclassing. However, its only to type match. We aren’t using inheritance to get behavior.

Why does this matter?

If we rely on inheritance we can only get what behavior the superclass gives us or that we override. With composition, we can mix and match decorators, even at runtime. For example you would either need to implement a DoubleCheese Pizza class or put “addCheese” methods on the Pizza class. Both of those are bad ideas because it is not open for extension for adding more condiments in the future.

Diagram


The component can be a Interface or Abstract class - sometimes code is existing and you don’t have a choice.


Java API Example


InputStreams. Each subclass of InputStream will have a constructor of the same type. This means you can wrap InputStreams to get the functionality you want. Example:

InputStream is =  new (GzipInputStream(new (BufferedInputStream(new FileInputStream(filename)));

FileInputStream reads in a file. 
BufferedInputStream adds read performance
GzipInputStream allows unzipping while reading

This design allows mixing and matching functionality instead of creating a class explosion per combination.

Design considerations


When using a decorator, you should avoid having code that checks for or depends on the concrete implementation. You have to write it against the abstract component type. If you start peeking at layers you are getting passed the true intent of a decorator. For example if your outer Bacon decorator needs to know that there is already Cheese on the pizza. In this case you should reconsider your design and use of a decorator.

How is a decorator different than a wrapper?

According to Wikipedia, A decorator pattern shares the alternative name Wrapper with adapter. A decorator is a type of wrapper. But a wrapper is not necessarily a decorator. I fact there are a bunch of similar wrapper type patterns. The subtlety has to do with use cases. A decorator must share the same type as the object it wraps. It is not meant to alter the interface, but add functionality transparently.