Awesome JavaScript Design Patterns

Why use them?

Because they're a powerful tool

Each design pattern solves a particular programming problem.

Because they help you maintain your code beauty.

Because, sometimes, you can't see the forest because of the trees

It's a way to say, but sometimes, you can't find the right answer, or any answer, it happened to me in the past, and that's why there are canonic algorithms and design patterns, to help you find a solution, to show you a bit of somebody's else thinking, to make you look outside the box, to make you see the forest.

Prototype Pattern

And there's the first one...

Simple Prototype Example

let person = {};

person.Bob = function(skill){
    this.skill = skill;
}

person.Bob.prototype = {
    workFor:function(remuneration){
        return 'I will work for ' + remuneration + ' dollars';
    },
    passionIs:function(passion){
        return 'My passion is ' + passion + ' but i do it very rare'
    },
    job:function(){
        return this.skill;
    }
}

let constructorBob = new person.Bob('constructor');
console.log(constructorBob.passionIs('cinematography'));
console.log(constructorBob.workFor(95175151));
console.log(constructorBob.job());

Not so simple Prototype example?

let desenator = {
};
desenator.shape = function(dimension,type){
    this.dimension = dimension;
    this.type = type;
}
desenator.shape.prototype = {
    putAt:function(coordX,coordY){
        this.div = document.createElement('div');
        if(this.type === 'circle'){
            this.div.style.borderRadius = '50%';
        }
        this.div.style.position = 'absolute';
        this.div.style.left = coordX + 'px';
        this.div.style.top = coordY + 'px';
    },
    draw:function(color){
        if(color !== undefined){
            this.div.style.backgroundColor = color;
        }
        this.div.style.border = '2px solid black';
        this.div.style.height = this.dimension + 'px';
        this.div.style.width = this.dimension + 'px';
        document.querySelector('body').appendChild(this.div);
    },
    reshape(dimension,type){
        this.dimension = dimension;
        this.type = type;
    }
}


let pictorBob = new desenator.shape(35,'circle');
pictorBob.putAt(15,16);
pictorBob.draw('red');
pictorBob.reshape(100,'square');
pictorBob.putAt(250,250);
pictorBob.draw('blue');

Module Pattern

The second one...

Main reason of using Module Pattern is...

Because you want to protect some functions, classes or object from user that are going to use your module, and in this purpose, you let them in the scope of your IFEE function, and return to user, only functions that are meant to be used in his interaction with your module.

 

In JavaScript we have closures, we don't need public and private descriptors.

Ladies and gentlemen, the module pattern

let spionulBob = (function(){
    'use strict';

    let _adevar = 'Sunt agent secret Bob!';
    let _minciuna = 'Sunt frizerul Bob!';

    function _spuneAdevar(){ //functie privata
        console.log(_adevar);
    }

    function _spuneMinciuna(){ //functie privata
        console.log(_minciuna);
    }

    function raspunde(safe){ //functie publica
        if(safe === true){
            _spuneAdevar();
        }else{
            _spuneMinciuna();
        }
    }

    return {
        raspunde:raspunde,
        raspunsStandard:'Sunt Bob'
    };
}());

spionulBob.raspunde(false);
console.log(spionulBob.raspunsStandard);
// console.log(spionulBob._adevar); eroare
// spionulBob._spuneMinciuna() eroare

Facade Pattern

Third one...

Revealing the Facade!

let spionulBob = (function(){
    'use strict';

    let _adevar = 'Sunt agent secret Bob!';
    let _minciuna = 'Sunt frizerul Bob!';

    function _spuneAdevar(){ //functie privata
        console.log(_adevar);
    }

    function _spuneMinciuna(){ //functie privata
        console.log(_minciuna);
    }

    function raspunde(safe){ //functie publica
        if(safe === true){
            _spuneAdevar();
        }else{
            _spuneMinciuna();
        }
    }
	//FACADE EXPOSED
    return {
        raspunde:raspunde,
        raspunsStandard:'Sunt Bob'
    };
  	//END OF FACADE AGE OF TERROR
}());

spionulBob.raspunde(false);
console.log(spionulBob.raspunsStandard);
// console.log(spionulBob._adevar); eroare
// spionulBob._spuneMinciuna() eroare

Observer Pattern

The LAST but not the LEAST...

What is Observer?

Observer Pattern is one of the most used JavaScript Dessign Patterns, there are a lot of situations where you can addapt it, starting from a streaming service and ending with a web-platform made to teach students , with exercises and recoreded lectures. 

Why Observer?

Because it's the best way to manage a collection of objects that are waiting to be notified by a specific process or are waiting for a specific action.

 

Best real-life usecase for Observer Pattern, is Youtube or Twitch Subscribtion Button . User's account is subscribed to a channel, that means that user's account is a observer that is going to be notified when the content creator upload a new video. If there wouldn't be a Observer Pattern, we'd have to do this task in a more time consuming manner, like, searching through a big graph for some specific connections between its vertexes.

Let's Observe Now...

var BobCelBunLaToate = function(){
    let clients = [];

    return {
        iaComanda:function(client){
            clients.push(client);
        },
        izgonesteClientul:function(client){
            let index = clients.indexOf(client);
            if(index > -1){
                clients.splice(index,1);
            }
            console.log('Afara din magazinul de de toate!');
        },
        notificaClientul:function(client){
            let index = clients.indexOf(client);
            if(index > -1){
                let cerere = clients[index].comanda();
                clients[index].notifica(cerere.toString() + ' dumneavoastra, este aproape gata!');
            }
        },
        notificaTotiClientii:function(){
            for(let i=0;i<clients.length;i++){
                let cerere = clients[i].comanda();
                clients[i].notifica(cerere.toString() + ' dumneavoastra, este aproape gata!');
            };
        }
    };
};
var Client = function(cerere){
    return {
        notifica:function(resp){
            console.log(resp);
        },
        comanda:function(){
            return cerere;
        }
    }
}

let bob = new BobCelBunLaToate();
let client1 = new Client('Friptura de porc');
let client2 = new Client('Rasol');
let client3 = new Client('Cianura');
bob.iaComanda(client1);
bob.iaComanda(client2);
bob.iaComanda(client3);
bob.notificaClientul(client2);
bob.notificaTotiClientii();

THE EXERCISE

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <canvas width = '1280' height='720'></canvas>
    <script>
        let btn = document.createElement('button');
        btn.innerText = 'Draw';
        btn.style.position = 'absolute';
        btn.style.left = '1300px';
        btn.style.top = '10px';
        document.querySelector('body').appendChild(btn);
        btn.addEventListener('click',function(){
            canvasHelper.splashCanvas('gray');
            canvasHelper.drawSquare(1100,75,50,'blue');
            canvasHelper.drawCircle(50,50,50,'yellow');
            canvasHelper.drawTriangle(400,400,35,'green');
            canvasHelper.drawTriangle(600,500,65,'green');
        });
        let circle_nr = document.createElement('p');
        let sq_nr = document.createElement('p');
        let tr_nr = document.createElement('p');
        circle_nr.style.position = 'absolute';
        sq_nr.style.position = 'absolute';
        tr_nr.style.position = 'absolute';
        circle_nr.style.left = '1310px';
        circle_nr.style.top = '50px';
        circle_nr.innerText = 'Number of Circles: 0';
        sq_nr.style.left = '1310px';
        sq_nr.style.top = '100px';
        sq_nr.innerText = 'Number of Squares: 0';
        tr_nr.style.left = '1310px';
        tr_nr.style.top = '150px';
        tr_nr.innerText = 'Number of Triangles: 0';
        document.querySelector('body').appendChild(circle_nr);
        document.querySelector('body').appendChild(sq_nr);
        document.querySelector('body').appendChild(tr_nr);
        let observerObj = function(p,type){
            return {
                notify:function(nr){
                   
                },
                type:function(){
                    
                }
            };
        };
		canvasHelper.add_Observer(obsCerc);
        canvasHelper.add_Observer(obsSq);
        canvasHelper.add_Observer(obsTr);
    </script>
</body>
</html>

Awesome JavaScript Design Patterns

By georgebadita

Awesome JavaScript Design Patterns

  • 479