DECORATOR

PATTERN

What is Decorator?

  • A Decorator is an object which adds functionality to another object dynamically. It can be used to enhance the behavior of an object without requiring the author to reopen its class.
     

  • Also known as WRAPPER

 

When you need it ?

 When you need to modifying existing systems where you may wish to add additional features to objects without the need to change the underlying code that uses them

CLASS DIAGRAM EXAMPLE

Without Decorator

With Decorator

PROBLEM STATEMENT

 

Imagine a scenario where we have a plain coffee . After that you just recall that you need to put some add-ons at customer’s choice. So you will need to give some add-ons like milk and whipped cream on the go.

Concrete Component

Without Decorator Pattern


Superclass
Let PlainCoffee = function() {...};
// Subclasses with different features
Let PlainWithMilkCoffee = function() {...};
Let PlainWithVanillaCoffee = function() {...};
Let PlainWithWhipCoffee = function() {...};
Let PlainWithMilkwithWhipCoffee = function() {...};
Let PlainMilkWithWhipCoffee = function() {...};
Let PlainMilkWithWhipAndVanillaCoffee = function() {...};
...

Decorator Design Pattern

/*
Coffee interface:
getCost()
getDescription()
*/

class SimpleCoffee{

    getCost() {
        return 10
    }

    getDescription() {
        return 'Simple coffee'
    }
}


class MilkCoffee {


    constructor(coffee) {
        this.coffee = coffee
    }

    getCost() {
        return this.coffee.getCost() + 2
    }

    getDescription() {
        return this.coffee.getDescription() + ', milk'
    }
}

class WhipCoffee {

    constructor(coffee) {
        this.coffee = coffee
    }

    getCost() {
        return this.coffee.getCost() + 5
    }

    getDescription() {
        return this.coffee.getDescription() + ', whip'
    }
}

class VanillaCoffee {

    constructor(coffee) {
        this.coffee = coffee
    }

    getCost() {
        return this.coffee.getCost() + 3
    }

    getDescription() {
        return this.coffee.getDescription() + ', vanilla'
    }
}
//Lets make a coffee now

let someCoffee

someCoffee = new SimpleCoffee()
console.log(someCoffee.getDescription())// Simple Coffee
console.log(someCoffee.getCost())// 10

someCoffee = new MilkCoffee(someCoffee)
console.log(someCoffee.getDescription())// Simple Coffee, milk
console.log(someCoffee.getCost())// 12

someCoffee = new WhipCoffee(someCoffee)
console.log(someCoffee.getDescription())// Simple Coffee, milk, whip
console.log(someCoffee.getCost())// 17

someCoffee = new VanillaCoffee(someCoffee)
console.log(someCoffee.getDescription())// Simple Coffee, milk, whip, vanilla
console.log(someCoffee.getCost())// 20

WHY use DECORETOR PATTERN ?

FLEXIBLE
Provide a flexible alternative to subclassing for extending functionality
 
BEHAVIOR MODIFICATION
Allow behavior modification at runtime rather than going back into existing code and making changes
 
PERMUTATION ISSUES
Nice solution to permutation issues because you can wrap a component with any number of decorators
 
Open/Closed principle
Classes should be open for extension but closed for modification.
 

REFERENCES

Decorator Pattern

By nur amirah

Decorator Pattern

  • 241