JS Design Patterns: Object Creation Patterns

So, Khabrovsk citizens, already this Thursday in OTUS the course "Fullstack JavaScript Developer" will start. And today we are sharing with you another author’s publication in anticipation of the start of the course.







Article author: Pavel Yakupov




In this article, we will talk about the simplest and most common design patterns in the Javascript language - and try to explain which ones to apply when.

What are design patterns in general? Design patterns is a term that is used for common, frequently used solutions to common problems in creating programs.



Simply put, design patterns are successful solutions that are used often enough. Design patterns as a concept formed even at a time when the JavaScript programming language was not mentioned, in the field of software engineering design patterns were described in detail in 1994 by the Big Four. However, in our article, we will turn to the implementation of some simple patterns in the JavaScript programming language.


Let's quickly go over the main types of design patterns:



Creation Design Patterns



As the name implies, these patterns are mainly used to create new objects. These include patterns such as Constructor, Factory, Prototype, and Singleton.



Structural Design Patterns



These patterns are associated with classes and composition of objects. They help to structure or restructure objects or their parts without disrupting the operation of the entire system.



Behavior Design Patterns



This type of design pattern is aimed at improving communication between different objects. Behavioral design patterns include Commander, Iterator, Mediator, Observer, State Pattern, Strategy, and Template.



In this article, we analyze only design patterns associated with creating objects - because they are a little easier and better suited for beginners to start creating their to-do applications, text RPGs in the console, simple games on Canvas, etc.



Pattern "Module"



This design pattern appeared in the JavaScript language, so to speak, involuntarily. Initially, the language did not think of counteracting such phenomena as pollution of the global scope (and in other languages, such as C # or C ++ there are namespace that solve this problem out of the box). In addition, the modules are partially necessary for reusing the code, because after they can be created and used for the first time, they can be connected to projects of other teams using man-hours much more competently.

The module module throughout its existence (already widely used in ES5) used IIFE (immediately called functional expressions).



Here is a simple example of the “Module” pattern:



const first_Module = (function() { let Surname = "Ivanov"; let Nickname = "isakura313"; function declare_Surname() { console.log(Surname); } return { declare_Nickname: function() { alert(Nickname); } } })(); first_Module.declare_Nickname(); console.log(Surname); //      
      
      





The “Module” pattern fully encapsulates the data contained in it. We can access them only using public methods, and until JavaScript implementations of public and private methods “out of the box” have to be implemented in this way.



Constructor Pattern



This is a design pattern designed to create an object. A constructor is a function that creates new objects. However, in JavaScript, objects can be created on the fly, even without a constructor function or class definition.

Constructor is one of the most commonly used design patterns. It is used to create objects of a certain type.



 //     to-do  //,    ,           class ItemDeal { constructor(name, color) { this.name = name; this.color = color; } } //     ,       localStorage  ? let item = new ItemDeal(`${text}`, `${select.value - 1}`); // text -   , a select.value -    let myJson = JSON.stringify(item); //        //localStorage,        //localStorage.setItem(item.name, myJson);
      
      





Factory pattern



The Factory pattern is another pattern focused on creating an object from a class. In it, we provide common interfaces that delegate the creation of a subclasses object.



This design pattern is most often used to manipulate a collection of objects that have both different and the same characteristics.

In the example below, we will create an enemy class (EnemyFactory) for our text quest. Yes, the example is quite simple, but this is the problem of design patterns: they are needed for "large" applications. If you have only three pictures flying out by clicking on the page, then no design patterns will be especially useful to you.



Okay, just show a piece of code for our text RPG in the console:



 class EnemyFactory{ constructor() { this.createEnemy = function(type) { let enemy; if (type === 'goblin' || type === 'ork') enemy = new Infantry(); else if (type === 'elf') enemy = new Archer(); enemy.attack = function() { return `The ${this._type} is attack`; }; return enemy; }; } } class Infantry { constructor() { this._type = 'goblin'; this.scream = function() { return 'AAAAAAAAA! Za ordu!!!'; }; } } class Archer { constructor() { this._type = 'elf'; this.magic_attack = function() { return 'Magic fog around you! You cant see!!'; }; } } const enemy_army = new EnemyFactory(); let newGoblin = enemy_army.createEnemy('goblin'); let newElf = enemy_army.createEnemy('elf'); console.log(newGoblin.attack()); console.log(newElf.attack()); console.log(newGoblin.scream()); console.log(newElf.magic_attack()); // 
      
      





Prototype Pattern



Here we use some type of “skeleton” of a real object to create a new object. And prototyping is the most native type of building OOP in JavaScript.



 //,     to-do  const itemDeal = { colorOfHeader: blue; //     .    ? create() { console.log("our item create"); //  item }, delete() { console.log("our item delete now"); //   item }, }; //     ,  to-do  //  ,   Trello. const newDeal = Object.create(itemDeal, { owner: { value: 'Paul' } }); console.log(newDeal.__proto__ === itemDeal); //true
      
      





The Prototype pattern is useful if your application can somehow expand or reduce functionality.



The Loner Pattern



Or, as he is better known, "Singleton." "Loner" is a special pattern in which only one instance of a class can exist. The pattern works as follows - the initialization of the object will work if there is not a single instance created or returned. If present, the triggered object will be returned.

Suppose we create a class of the protagonist, and we want it to be 1, not 4, as in Jumanji.



 class Hero { constructor(name) { if (Hero.exists) { return Hero.instance; } this._name = name; Hero.instance = this; Hero.exists = true; return this; } getName() { return this._name; } setName(name) { this._name = name; } } //    const smolder = new Hero('Smolder!'); console.log(smolder.getName()); // Smolder! const ruby = new Hero('Ruby'); console.log(ruby.getName()); // Smolder! // ,       .         . //           
      
      





So thank you all for your attention! I hope that this article will serve as a good start for OOP in JavaScript (although, to be honest, my colleague with many years of experience in both Java and JavaScript, OOP is not very developed there, to put it mildly). However, in the new standards, the language has improved significantly, and I'm sure this methodology will only be used more often (or Dart will come and replace everything).



Useful links:



developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create

learn.javascript.ru/class

developer.mozilla.org/en/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript



All Articles