Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    JavaScript Decorator

    Published Dec 07, 2019 [  Node.js  ]

    Decorator is a structural pattern that consists of dynamically augmenting the behavior of an existing object. It’s different from classical inheritance, because the behavior is not added to all the objects of the same class, but only to the instances that are explicitly decorated.

    Implementation-wise, it is very similar to the Proxy Pattern, but instead of enhancing or modifying the behavior of the existing interface of an object, it augments it with new functionalities.

    The Decorator object is extending the Component object by adding the methodC() operation. The existing methods are usually delegated to the decorated object, without further processing. Of course,if necessary we can easily combine the Proxy pattern so that the calls to the existing methods can be intercepted and manipulated as well.

    Techniques for implementing Decorators

    Composition

    Using composition, the decorated component is wrapped around a new object that usually inherits from it. The Decorator in this case simply needs to define the new methods, while delegating the existing ones to the original component

    function decorate(component){
        const proto = Object.getPrototypeOf(component)
    
        function Decorator(component){
            this.component = component
        }
    
        Decorator.prototype = Object.create(proto)
    
        // new method
        Decorator.prototype.greetings = function(){
            return 'Hi!'
        }
    
        // delegate method
        Decorator.prototype.hello = function(){
            return this.component.hello.apply(this.component, arguments)
        }
    
        return new Decorator(component)
    }
    

    Object augmentation

    Object decoration can also be achieved by simply attaching new methods directly to the decorated object

    function decorate(component){
        // new method
        component.greetings = () => {
            // ...
        }
        return component
    }
    

    Decorating a LevelUP database

    Implementing a LevelUP plugin

    module.exports = function levelSubscribe(db){
        db.subscribe = (pattern, listener) => {
            db.on('put', (key, val) => {
                const match = Object.keys(pattern).every(k => (pattern[k] === val[k]))
                if(match){
                    listener(key, val)
                }
            })
        }
        return db;
    }
    
    const level = require('level')
    const levelSubscribe = require('./levelSubscribe')
    
    let db = level(__dirname + '/db', {valueEncoding: 'json'})
    db = levelSubscribe(db)
    
    db.subscribe(
        {doctype: 'tweet', language: 'en'},
        (k, val) => console.log(val)
    )
    db.put('1', {doctype: 'tweet', text: 'Hi', language: 'en'})
    db.put('2', {doctype: 'company', name: 'ACME Co.'})
    

    References

    • Node.js Design Patterns