What is the Decorator Pattern?
The Decorator Design Pattern is a way of adding additional functionality to an existing object without modifying its structure. This is done by wrapping the existing object with an outer object to extend its behavior.
Why is the Decorator Design Pattern useful?
The Decorator Design Pattern is useful because it allows us to easily add additional functionality to an existing object without having to modify its structure. This is especially useful when the functionality we need is complex or would require a lot of code to implement.
Example in Javascript
Logging Decorator
In this example, we will create a Logging Decorator that logs a message every time a function is called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token comment">// Create the base function</span> <span class="token keyword">function</span> <span class="token function">getData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Do something</span> <span class="token punctuation">}</span> <span class="token comment">// Create the LoggingDecorator</span> <span class="token keyword">function</span> <span class="token function">LoggingDecorator</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Logging...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// Decorate the function</span> <span class="token keyword">let</span> decoratedFn <span class="token operator">=</span> <span class="token function">LoggingDecorator</span><span class="token punctuation">(</span>getData<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Call the decorated function</span> <span class="token function">decoratedFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Logs 'Logging...'</span> |
Caching Decorator
In this example, we will create a Caching Decorator that stores the result of a function call in a cache. We will also add a mechanism to check if the result is already present in the cache and return its value without calling the function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <span class="token comment">// Create the base function</span> <span class="token keyword">function</span> <span class="token function">getData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Do something</span> <span class="token punctuation">}</span> <span class="token comment">// Create the cache</span> <span class="token keyword">let</span> cache <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Create the CachingDecorator</span> <span class="token keyword">function</span> <span class="token function">CachingDecorator</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Check if the result is in the cache</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>cache<span class="token punctuation">[</span>fn<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> cache<span class="token punctuation">[</span>fn<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Call the function and store the result in the cache</span> <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> cache<span class="token punctuation">[</span>fn<span class="token punctuation">]</span> <span class="token operator">=</span> result<span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// Decorate the function </span> <span class="token keyword">let</span> decoratedFn <span class="token operator">=</span> <span class="token function">CachingDecorator</span><span class="token punctuation">(</span>getData<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Call the decorated function</span> <span class="token function">decoratedFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Throttling Decorator
In this example, we will create a Throttling Decorator that limits a function to run no more than once in a certain amount of time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token comment">// Create the base function </span> <span class="token keyword">function</span> <span class="token function">getData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Do something</span> <span class="token punctuation">}</span> <span class="token comment">// Create the ThrottlingDecorator</span> <span class="token keyword">function</span> <span class="token function">ThrottlingDecorator</span><span class="token punctuation">(</span><span class="token parameter">fn<span class="token punctuation">,</span> delay</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> lastCallTime<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Check if the function was called before </span> <span class="token keyword">if</span> <span class="token punctuation">(</span>lastCallTime <span class="token operator">&&</span> <span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> lastCallTime<span class="token punctuation">)</span> <span class="token operator"><</span> delay<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Call the function and store the time</span> lastCallTime <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// Decorate the function</span> <span class="token keyword">let</span> decoratedFn <span class="token operator">=</span> <span class="token function">ThrottlingDecorator</span><span class="token punctuation">(</span>getData<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Call the decorated function</span> <span class="token function">decoratedFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Conclusion
The Decorator Design Pattern is a way to easily extend the functionality of an existing object without having to modify its structure. We’ve seen some code samples and can see how this pattern makes adding additional functionality to objects very easy.
And Finally
As always, I hope you enjoyed this article and learned something new.
Thank you and see you in the next articles!
If you liked this article, please give me a like and subscribe to support me. Thank you.