Table of content

Decorator Design Pattern

Decorator pattern allows a user to add new functionality to an existing object without altering its structure. This type of design pattern comes under structural pattern as this pattern acts as a wrapper to the existing class.

That is there will be additional features added to the original object. The component, which adds these additional features is called the Decorator.

The Decorator class in this pattern act as a wrapper object which dynamically attaches additional features to the original object at run-time.

Definition:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality

As in the definition, the main intent of the decorator pattern is to attach additional responsibilities and features dynamically to an object. However, at the same time, other instances or base class will not be affected by the new dynamic change. Only the individual object will receive the new modification.

Since this pattern solves the dynamic feature addition at run-time, it resolves the problem of the complex sub-classing requirement when extending base class functionality.

Example for Decorator Design Pattern

It’s like adding cheese topping to a pizza or adding walnut and chocolate source topping to an ice-cream. You can add any kind of cheese or sauce to the pizza just before serving to the customer, yet base pizza remains unchanged.

Likewise, you can request walnut or cherries on a vanilla ice cream or you can change the mind and ask to add only chocolate topping and cherry sauce. Base vanilla ice cream won’t change and you can have whatever topping you like on the ice cream.

If there are 20 people in the group, they can request 20 vanilla ice creams with different toppings, nuts, and fruits on time of serving.

// Decorator pattern

pub fn decorator() { let obj = BaseObject { value: 100 }; process(&obj);

let decorator_obj = DecoratorObject { base: obj, more_value: 999 }; process(&decorator_obj);

decorator_obj.do_something_more(); }

trait Component { fn do_something(&self); }

trait Decorator: Component { fn do_something_more(&self); }

struct BaseObject { value: usize, }

impl Component for BaseObject { fn do_something(&self) { println!("calculate value: {}", self.value); } }

struct DecoratorObject { base: BaseObject, more_value: usize, }

impl Component for DecoratorObject { fn do_something(&self) { self.base.do_something() } }

impl Decorator for DecoratorObject { fn do_something_more(&self) { println!("calculate more: {}", self.more_value); } }

fn process(c: &Component) { c.do_something(); }

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions