Design Patterns
class: center, middle .title[ Front-end training # Design Patterns ] --- # What is pattern? - A pattern is a recurring solution to a standard problem in a context. - Each pattern is a three-part rule which expresses a relation between a certain context, a problem, and a solution. --- # Background - Started in 1987 by Ward Cunningham and Ken Beck who were working with Smalltalk and designing GUIs. - Popularized by Gamma, Helm, Johnson and Vlissides (The gang of four, Go4) - The three of Go4 were working on frameworks (E++,Unidraw, HotDraw) - Design pattern use a consistent documentation approach - Design pattern are granular and applied at different levels such as frameworks, subsystems and sub-subsystems - Design patterns are often organized as creational, structural or behavioral --- # Types of Patterns - ### Creational - Deal with initializing and configuring classes and objects - ### Structural - Deal with decoupling interface and implementation of classes and objects - Composition of classes or objects - ### Behavioural - Deal with dynamic interactions among societies of classes and objects - Distribute responsibility --- # Module - ### Wherefore In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. - ### Howto Module is a combination of 2 simple patterns: - self-executing function - private variables and methods --- # Module-object ``` var module = (function () { var counter = 0; function increaseCounter() { counter++; } function resetCounter() { console.log(counter); counter = 0; } return { increase: increaseCounter, reset: resetCounter }; })(); // Usage: // Increment our counter module.increase(); // Check the counter value and reset // Outputs: 1 module.reset(); ``` --- # Module-constructor ``` var Neuron = (function (jQuery, Underscore) { var cell = function () {}; function say(message) { console.log(message); } cell.prototype = { migrate: function() { // cell is going to find a better place say('travelling'); }, learn: function(subj) { // trying something new say('f***ing ' + subj); }, duplicate: function() {} }; return cell; })($, _); // Usage: // Creates new neuron instance var brainCell = new Neuron(); // Outputs: travelling brainCell.migrate(); // Outputs: f***ing math brainCell.learn('math'); ``` --- # Module. Pros/Cons - ### Advantages - scope limitation - splitting the project into logical blocks - reuse - ### Disadvantages - modules structure organization (we still need amd, cjs, etc.) --- # Singleton - ### Wherefore - Provide single instance of class. When you try to create another instance, the program should receive an item that has already been created. - ### Howto - Using module pattern --- # Singleton ``` var Singleton = (function () { var instance; function createInstance() { var object = new Object("I am the instance"); return object; } return { getInstance: function () { // creates instans if it doesn't exist if (!instance) { instance = createInstance(); } return instance; } }; })(); // Usage: // Creates new instance var instance1 = Singleton.getInstance(); var instance2 = Singleton.getInstance(); // Outputs: true console.log(instance1 === instance2); ``` --- # Singleton. Pros/Cons - ### Advantages - controlled access to a single instance - ### Disadvantages - global access - problems with testing are possible - often there is a desire to expand singleton --- # Factory - ### Wherefore - Factory can provide a generic interface for creating objects, where we can specify the type of factory object we wish to be created. - ### Howto - Using the factory method, which will select the appropriate constructor. --- # Build-in Factory ``` var o = new Object(), n = new Object(1), s = Object(‘1’), b = Object(true); // test o.constructor === Object; // true n.constructor === Number; // true s.constructor === String; // true b.constructor === Boolean; // true ``` --- # Factory. Example part 1 ``` // parent constructor function CarMaker() {} // a method of the parent CarMaker.prototype.drive = function () { return “Vroom, I have “ + this.doors + “ doors”; }; // the static factory method CarMaker.factory = function (type) { var constr = type, newcar; if (typeof CarMaker[constr] !== “function”) { // error appears } // at this point the constructor is known to exist // let's have it inherit the parent but only once if (typeof CarMaker[constr].prototype.drive !== “function”) { CarMaker[constr].prototype = new CarMaker(); } newcar = new CarMaker[constr](); return newcar; }; ``` --- # Factory. Example part 2 ``` // define specific car makers CarMaker.Compact = function () { this.doors = 4; }; CarMaker.Convertible = function () { this.doors = 2; }; CarMaker.SUV = function () { this.doors = 24; }; // Usage: // objects creating var corolla = CarMaker.factory(‘Compact’), solstice = CarMaker.factory(‘Convertible’), cherokee = CarMaker.factory(‘SUV’); corolla.drive(); // “Vroom, I have 4 doors” solstice.drive(); // “Vroom, I have 2 doors” cherokee.drive(); // “Vroom, I have 24 doors” ``` --- # Factory. Pros/Cons - ### Advantages - allows you to make the code more flexible - provides a single interface for creating objects - ### Disadvantages - difficult to add support for new types of objects --- # Observer/PubSub - ### Wherefore - This is where the objects in a system may subscribe to other objects and be notified by them when an event of interest occurs. - ### Howto - Using javascript events --- # Observer/PubSub ``` (function( $ ) { var o = $( {} ); $.each({ trigger: 'publish', on: 'subscribe', off: 'unsubscribe' }, function( key, val ) { jQuery[val] = function() { o[key].apply( o, arguments ); }; }); })( jQuery ); $.getJSON('http://search.twitter.com/search.json?q=dogs&callback=?', function( results) { $.publish( 'twitter/results', results ); }); $.subscribe( 'twitter/results', function( e, results ) { $('body').html( $.map( results.results, function( obj, index) { return '
' + obj.text + '
'; }).join('') ); }); ``` --- # Observer. Pros/Cons - ### Advantages - weakens the relationship between objects - helps to simplify objects - ### Disadvantages - system is getting less transparent - performance degradation --- # Mediator - ### Wherefore - Mediator is a behavioral design pattern that allows us to expose a unified interface through which the different parts of a system may communicate. - ### Howto - Using additional object --- # Mediator. Part 1 ``` function Player(name) { this.points = 0; this.name = name; } Player.prototype.play = function () { this.points += 1; mediator.played(); }; var scoreboard = { // HTML element to be updated element: document.getElementById('results'), // update the score display update: function (score) { // playing with DOM } }; ``` --- # Mediator. Part 2 ``` var mediator = { // all the players players: {}, // initialization setup: function () { var players = this.players; players.home = new Player('Home'); players.guest = new Player('Guest'); }, // someone plays, update the score played: function () { var players = this.players, score = { Home: players.home.points, Guest: players.guest.points }; scoreboard.update(score); }, keypress: function (e) { e = e || window.event; // IE if (e.which === 49) { // key "1" mediator.players.home.play(); return; } if (e.which === 48) { // key "0" mediator.players.guest.play(); return; } } }; ``` --- # Mediator. Part 3 ``` mediator.setup(); window.onkeypress = mediator.keypress; // game over in 30 seconds setTimeout(function () { window.onkeypress = null; alert('Game over!'); }, 30000); ``` --- # Mediator. Pros/Cons - ### Advantages - weakens the relationship between objects - helps to simplify objects - ### Disadvantages - system is getting less transparent - performance degradation --- # Facade - ### Wherefore - This pattern provides a convenient higher-level interface to a larger body of code, hiding its true underlying complexity. - ### Howto - Creating set of facade methods and joining them in one place --- # Facade ``` var pageFacade = { updateMenu: function() { loadData(); resizeColumn(); updateCounter(); setLog(); }, doSmthElse: function() { // a lot of methods } }; // Usage: // Instead of all functions invocation pageFacade.updateMenu(); ``` --- # Facade. Pros/Cons - ### Advantages - easy access to a complex system - resistance to changes - ### Disadvantages - It’s not always obvious what's going on in a certain method - methods can be duplicated --- # Benefits of Design Patterns - Design patterns enable large-scale reuse of software architectures and also help document systems - Patterns help improve developer communication - Pattern names form a common vocabulary - Patterns help ease the transition to Object Oriented technology --- # Drawbacks of Design Patterns - Patterns do not lead to direct code reuse - Patterns are deceptively simple - Teams may suffer from pattern overload - Patterns are validated by experience and discussion rather than by automated testing - Integrating patterns is a human-intensive activity