Skip to content

Decorator Design Pattern

Video Lecture

Section Video Links
Decorator Pattern Decorator Decorator Pattern  
Decorator Use Case Decorator Use Case Decorator Use Case  

Overview

... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.

Terminology

... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.

Decorator UML Diagram

Decorator Pattern UML Diagram

Source Code

./src/decorator/decorator-concept.ts

 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
30
31
32
33
34
35
// Decorator Concept Sample Code

interface IComponent {
    method(): string
}

class Component implements IComponent {
    method(): string {
        return 'Component Method'
    }
}

class Decorator implements IComponent {
    #object: IComponent

    constructor(object: IComponent) {
        this.#object = object
    }

    method(): string {
        return `Decorator Method(${this.#object.method()})`
    }
}

// The Client
const COMPONENT = new Component()
console.log(COMPONENT.method())

// The component can be decorated
const Decorated = new Decorator(COMPONENT)
console.log(Decorated.method())

// The decorated component can be decorated again
const Decorated2 = new Decorator(Decorated)
console.log(Decorated2.method())

Output

node ./dist/decorator/decorator-concept.js
Component Method
Decorator Method(Component Method)
Decorator Method(Decorator Method(Component Method))

Decorator Use Case

... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.

Example UML Diagram

Decorator Pattern in Context

Source Code

./src/decorator/client.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// Decorator Use Case Example Code

import Value from './value'
import Add from './add'
import Sub from './sub'

const A = Value(1)
const B = Value(2)
const C = Value(5)

console.log(Add(A, B).value)
console.log(Add(A, 100).value)
console.log(Sub(C, A).value)
console.log(Sub(Add(C, B), A).value)
console.log(Sub(100, 101).value)
console.log(Add(Sub(Add(C, B), A), 100).value)
console.log(Sub(123, Add(C, C)).value)
console.log(Add(Sub(Add(C, 10), A), 100).value)
console.log(A.value)
console.log(B.value)
console.log(C.value)

./src/decorator/value.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
export interface IValue {
    value: number
}

class _Value implements IValue {
    value: number
    constructor(value: number) {
        this.value = value
    }
}

export default function Value(value: number): IValue {
    return new _Value(value)
}

./src/decorator/add.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import { IValue } from './value'

class _Add implements IValue {
    value: number
    constructor(val1: IValue | number, val2: IValue | number) {
        const left = Object.prototype.hasOwnProperty.call(val1, 'value')
            ? (val1 as IValue).value
            : (val1 as number)
        const right = Object.prototype.hasOwnProperty.call(val2, 'value')
            ? (val2 as IValue).value
            : (val2 as number)
        this.value = left + right
    }
}

export default function Add(
    val1: IValue | number,
    val2: IValue | number
): IValue {
    return new _Add(val1, val2)
}

./src/decorator/sub.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import { IValue } from './value'

class _Sub implements IValue {
    value: number
    constructor(val1: IValue | number, val2: IValue | number) {
        const left = Object.prototype.hasOwnProperty.call(val1, 'value')
            ? (val1 as IValue).value
            : (val1 as number)
        const right = Object.prototype.hasOwnProperty.call(val2, 'value')
            ? (val2 as IValue).value
            : (val2 as number)
        this.value = left - right
    }
}

export default function Sub(
    val1: IValue | number,
    val2: IValue | number
): IValue {
    return new _Sub(val1, val2)
}

Output

node ./dist/decorator/client.js
3
101
4
6
-1
106
113
114
1
2
5

Summary

... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.