Patrones de dise帽o JS: Patrones de creaci贸n de objetos

Entonces, ciudadanos de Khabrovsk, ya este jueves en OTUS comenzar谩 el curso "Fullstack JavaScript Developer" . Y hoy compartimos con usted la publicaci贸n de otro autor en anticipaci贸n al inicio del curso.



Autor del art铆culo: Pavel Yakupov


En este art铆culo, hablaremos sobre los patrones de dise帽o m谩s simples y comunes en el lenguaje Javascript, y trataremos de explicar cu谩les aplicar cuando.
驴Qu茅 son los patrones de dise帽o en general? Patrones de dise帽o es un t茅rmino que se utiliza para soluciones comunes y de uso frecuente a problemas comunes en la creaci贸n de programas.

En pocas palabras, los patrones de dise帽o son soluciones exitosas que se utilizan con la frecuencia suficiente. Los patrones de dise帽o como un concepto formado incluso en un momento en que no se mencionaba el lenguaje de programaci贸n JavaScript, en el campo de la ingenier铆a de software, los Cuatro Grandes describieron en detalle los patrones de dise帽o en 1994. Sin embargo, en nuestro art铆culo, pasaremos a la implementaci贸n de algunos patrones simples en el lenguaje de programaci贸n JavaScript.

Repasemos r谩pidamente los principales tipos de patrones de dise帽o:

Patrones de dise帽o de creaci贸n


Como su nombre lo indica, estos patrones se utilizan principalmente para crear nuevos objetos. Estos incluyen patrones como Constructor, Factory, Prototype y Singleton.

Patrones de dise帽o estructural


Estos patrones est谩n asociados con clases y composici贸n de objetos. Ayudan a estructurar o reestructurar objetos o sus partes sin interrumpir el funcionamiento de todo el sistema.

Patrones de dise帽o de comportamiento


Este tipo de patr贸n de dise帽o tiene como objetivo mejorar la comunicaci贸n entre diferentes objetos. Los patrones de dise帽o de comportamiento incluyen Comandante, Iterador, Mediador, Observador, Patr贸n de Estado, Estrategia y Plantilla.

En este art铆culo, analizamos solo los patrones de dise帽o relacionados con la creaci贸n de objetos, porque son un poco m谩s simples y m谩s adecuados para que los principiantes comiencen a crear sus aplicaciones de tareas pendientes, juegos de rol de texto en la consola, juegos simples en Canvas, etc.

Patr贸n "M贸dulo"


Este patr贸n de dise帽o apareci贸 en el lenguaje JavaScript, por as铆 decirlo, involuntariamente. Inicialmente, el lenguaje no pens贸 en contrarrestar fen贸menos como la contaminaci贸n del alcance global (y en otros lenguajes, como C # o C ++, hay espacios de nombres que resuelven este problema de forma inmediata). Adem谩s, los m贸dulos son parcialmente necesarios para reutilizar el c贸digo, porque despu茅s de que se pueden crear y usar por primera vez, se pueden conectar a proyectos de otros equipos utilizando horas hombre de manera mucho m谩s competente.
El m贸dulo del m贸dulo a lo largo de su existencia (ya en ES5 fue ampliamente utilizado) us贸 IIFE (inmediatamente llamado expresiones funcionales).

Aqu铆 hay un ejemplo simple del patr贸n "M贸dulo":

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); //       

Patr贸n de "m贸dulo" encapsula completamente los datos, que est谩n encerrados en ella. Podemos referirnos a ellos s贸lo con la ayuda de m茅todos p煤blicos, y si bien en JavaScript parece implementaci贸n de m茅todos p煤blicos y privados "fuera de la caja" es necesario para implementar el m贸dulo de esta manera.

El patr贸n de "dise帽ador"


Este patr贸n de dise帽o est谩 dise帽ado para crear un objeto. Constructor es una funci贸n que crea nuevos objetos. Sin embargo, en los objetos de JavaScript se pueden crear "sobre la marcha", sin ni siquiera la funci贸n constructora o definici贸n de clase.
Constructor es uno de los patrones de dise帽o m谩s com煤nmente utilizados. Se usa para crear objetos de un tipo particular.

 //     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); {texto}` `$ {select.value - //     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); 

Patr贸n "de f谩brica"


patr贸n de f谩brica es otro patr贸n orientado a crear un objeto de la clase. En ella proporcionamos interfaces comunes para delegar la creaci贸n de un objeto de subclase (subclases).

Este patr贸n de dise帽o es la m谩s utilizada para manipular colecciones de objetos que son diferentes y las mismas caracter铆sticas.
En el siguiente ejemplo, creamos un enemigo de clase (EnemyFactory) para nuestra b煤squeda de texto. S铆, el ejemplo bastante simple, pero este es el problema de los patrones de dise帽o: se necesitan para las aplicaciones "grandes". Si usted tiene s贸lo tres im谩genes volar haciendo clic en la p谩gina - luego dise帽ar ning煤n extra que los patrones y no ser谩n 煤tiles.

Est谩 bien, s贸lo mostrar una pieza de c贸digo RPG nuestro texto en la consola:

 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()); //  escriba === 'ork') enemigo = new infanter铆a (); 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()); //  ) = enemigo nueva Archer (); 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()); //  attack`; 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()); //  ); 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()); //  ); 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()); //  

El patr贸n de "prototipo"


Aqu铆 se utiliza alg煤n tipo de "esqueleto" del objeto para crear un nuevo objeto. Una de prototipos es el tipo nativo del edificio de la OLP en 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 ; //,     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 ); //,     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 due帽o: {valor: 'Paul'}}); //,     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 

El patr贸n de "prototipo" es 煤til si de alguna manera se puede ampliar o reducir la funcionalidad de la aplicaci贸n.

Patr贸n "Singleton"


O como es m谩s conocido, 芦Singleton禄. "脷nico" es un patr贸n especial en el que puede existir s贸lo una instancia de la clase. El patr贸n es el siguiente - el trabajo objeto de inicializaci贸n si no hay una instancia creada o devuelto. Si la hay, entonces devolver el objeto iniciado.
Supongamos que creamos una clase del h茅roe, y nosotros queremos que sea 1 en lugar de 4 como en 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! // ,       .         . //            !'); 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! // ,       .         . //            '); 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! // ,       .         . //            

As铆, gracias a todos por su atenci贸n! Espero que alguien, este art铆culo servir谩 como un buen inicio de la OLP en JavaScript (aunque, para ser honesta confesi贸n de mis colegas con a帽os de experiencia y en Java, y en JavaScript, programaci贸n orientada a objetos all铆, por decirlo suavemente, no muy desarrollada). Sin embargo, en el lenguaje de las nuevas normas ha mejorado mucho, y estoy seguro de que esta metodolog铆a seguir谩 siendo s贸lo es m谩s probable que se utilicen (o reemplazar谩 el dardo y todo).

Enlaces de inter茅s:

developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/create
learn.javascript.ru/class
developer.mozilla.org/ru/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

Source: https://habr.com/ru/post/468723/


All Articles