<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Patrones de Diseño - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Patrones de Diseño - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 08:28:28 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/tag/patrones-de-diseno/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Los 3 tipos de patrones de diseño que todo desarrollador debería saber (con códigos de ejemplo de cada uno) ]]>
                </title>
                <description>
                    <![CDATA[ ¿Qué es un Patrón de Diseño? Los patrones de diseño son soluciones a nivel de diseño para problemas recurrentes que nosotros como ingenieros de software enfrentamos frecuentemente. No es código - Repito ❌CÓDIGO. Es como una descripción sobre como atacar estos problemas y diseñar una solución. Usar estos patrones es ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/los-3-tipos-de-patrones-de-diseno-que-todo-desarrollador-deberia-saber-con-codigos-de-ejemplo-de-cada-uno/</link>
                <guid isPermaLink="false">64a3664013b6b807a602ecd3</guid>
                
                    <category>
                        <![CDATA[ Patrones de Diseño ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sebastian Mendez ]]>
                </dc:creator>
                <pubDate>Wed, 13 Sep 2023 19:05:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/07/design-patterns-everywhere.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/the-basic-design-patterns-all-developers-need-to-know/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The 3 Types of Design Patterns All Developers Should Know (with code examples of each)</a>
      </p><h1 id="-qu-es-un-patr-n-de-dise-o"><strong>¿Qué es un Patrón de Diseño?</strong></h1><p>Los patrones de diseño son soluciones a nivel de diseño para problemas recurrentes que nosotros como ingenieros de software enfrentamos frecuentemente. No es código - Repito ❌<strong>CÓDIGO</strong>. Es como una descripción sobre como atacar estos problemas y diseñar una solución.</p><p>Usar estos patrones es considerado una buena práctica, ya que el diseño de la solución ha sido probado y comprobado, resulta en una legibilidad más alta en el código final. Los patrones de diseño son frecuentemente creados y usados en lenguajes de Programación Orientada a Objetos, como Java, en el cuál la mayoría de los ejemplos estarán escritos desde ahora en adelante.</p><h2 id="tipos-de-patrones-de-dise-o"><strong>Tipos de patrones de diseño</strong></h2><p>Hay cerca de 26 patrones actualmente descubiertos (difícilmente creo que los cubriré todos...).</p><p>Estos 26 puede ser clasificados en 3 tipos:</p><ol><li>Creacionales: Estos patrones son diseñados para la instanciación de clases. Pueden ser patrones de creación tanto de clases como de objetos.</li><li>Estructurales: Estos patrones son diseñados con respecto a la estructura y composición de una clase. La principal meta de la mayoría de estos patrones es la de incrementar la funcionalidad de la(s) clase(s) involucrada(s), sin cambiar mucho de su composición.</li><li>De comportamiento: Estos patrones son diseñados dependiendo de cómo una clase se comunica con otras.</li></ol><p>En este artículo, veremos cada tipo de patrón de diseño en esta clasificación, empezando desde el más básico.</p><h2 id="tipo-1-creacional-el-patr-n-de-dise-o-singleton"><strong>Tipo 1: Creacional - El patrón de diseño Singleton</strong></h2><p>El patrón de diseño Singleton es un patrón creacional, del cual su objetivo es crear una sola instancia de una clase y proveer un solo punto de acceso global para ese objeto. Un ejemplo comúnmente usado es la clase Calendar en Java, donde no puedes hacer una instancia de esa clase. También utiliza su propio método <code>getInstance()</code> para obtener el objeto a ser usado.</p><p>Una clase que use el patrón de diseño singleton incluirá:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/07/singleton-class-diagram.png" class="kg-image" alt="singleton-class-diagram" width="600" height="400" loading="lazy"><figcaption>Diagrama de clase Singleton</figcaption></figure><ol><li>Una variable estática, que contiene la única instancia de la clase</li><li>Un constructor privado, para que así no se pueda instanciar en ningún otro lado.</li><li>Un método publico estático, para retornar la única instancia de la clase.</li></ol><p>Hay muchas maneras diferentes de implementar el diseño singleton. Hoy cubriré cada una de las implementaciones de:</p><p>1. Instanciación ansiosa</p><p>2. Instanciación perezosa</p><p>3. Instanciación segura para subprocesos</p><h3 id="castor-ansioso"><strong>Castor ansioso</strong></h3><pre><code class="language-java">public class EagerSingleton {
	// crear una instancia de la clase.
	private static EagerSingleton instance = new EagerSingleton();

	//constructor privado para evitar que sea instanciado fuera de la clase.
	private EagerSingleton() {  }

	// devuelve la única instancia de la clase.
	public static EagerSingleton getInstance() {
		return instance;
	}
}</code></pre><p>Este tipo de instanciación sucede durante la carga de la clase, ya que la creación de la instancia de la variable se produce fuera de cualquier método. Esto supone un gran inconveniente si la aplicación cliente no utiliza esta clase en absoluto. El plan de contingencia, si esta clase no es usada, es la instanciación perezosa.</p><h3 id="d-as-de-pereza">Días de pereza</h3><p>No hay tanta diferencia con la implementación de arriba. Las principales diferencias son que la variable estática es inicialmente declarada como nula, y es solo instanciada dentro del método <code>getInstance()</code> si, y solo si, la variable de la instancia permanece nula en el momento que se revisa.</p><pre><code class="language-java">public class LazySingleton {
	// inicializa la instancia con valor nulo.
	private static LazySingleton instance = null;

	// constructor privado para evitar que sea instanciada fuera de esta clase.
	private LazySingleton() {  }
	
    // revisa si la instancia es nula, si lo es crea el objeto.	
	public static LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
}</code></pre><p>Esto soluciona un problema, pero otro sigue existiendo. ¿Qué tal si dos clientes diferentes acceden a la clase Singleton al mismo tiempo, en el mismo milisegundo? Bueno, ellos revisarían si la instancia es nula al mismo tiempo, y la encontrarían como verdadera, y entonces crearían dos instancias de la clase para cada petición de los dos clientes. Para solucionar esto, la instanciación segura de hilo debe ser implementada.</p><h3 id="la-seguridad-para-subprocesos-es-clave"><strong>La seguridad (para subprocesos) es clave</strong></h3><p>En java, la palabra clave "synchronized" es usada en métodos u objetos para implementar seguridad de subprocesos, con la finalidad de que solo un hilo a la vez acceda a un recurso en particular. La instanciación de la clase es puesta dentro de un bloque sincronizado, para que el método solo pueda ser accesible por solo un cliente en un momento dado.</p><pre><code class="language-java">public class ThreadSafeSingleton {
	// inicializa la instancia con valor nulo.
	private static ThreadSafeSingleton instance = null;

	// constructor privado para evitar que sea instanciada fuera de esta clase.
	private ThreadSafeSingleton() {  }
    
	// revisa si la instancia es nula, dentro de un bloque síncrono, si lo es crea el objeto.	
	public static ThreadSafeSingleton getInstance() {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
		return instance;
	}
}</code></pre><p>La sobrecarga de procesamiento que resulta del método sincronizado es elevada y reduce el rendimiento de toda la operación.</p><p>Por ejemplo, si la variable de la instancia ya ha sido inicializada, entonces cada vez que cualquier cliente acceda al método <code>getInstance()</code>, el método <code>synchronized</code> es ejecutado y el rendimiento disminuye. Esto solo sucede para revisar si el valor de la variable <code>instance</code> es nula. Si se encuentra que, si es nula, se sale del método.</p><p>Para reducir la sobrecarga, se usa el doble cierre. La revisión se realiza antes del método <code>synchronized</code> &nbsp;y si el valor es solo nulo, hace que el método <code>synchronized</code> se ejecute.</p><pre><code class="language-java">// se usa el doble cierre para reducir la sobrecarga del método síncrono ("synchronized")
public static ThreadSafeSingleton getInstanceDoubleLocking() {
	if (instance == null) {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
	}
	return instance;
}</code></pre><p>Ahora a la siguiente clasificación.</p><h2 id="tipo-2-estructurales-el-patr-n-de-dise-o-decorador"><strong>Tipo 2: Estructurales - El patrón de diseño Decorador</strong></h2><p>Te voy a dar un pequeño escenario para dar un mejor contexto del por qué y dónde deberías usar el patrón Decorador.</p><p>Imagina que tienes una cafetería, y como cualquier novato, empiezas con solo dos tipos de café simples, la mezcla de la casa y el negro tostado. En tu sistema de cobro, había una clase para las diferentes mezclas de café, las cuales heredan de la clase abstracta de bebidas. De hecho, la gente empieza a venir y a tomar tu maravilloso (aunque amargo) café. Entonces hay novatos del café que, dios no lo quiera, quieren azúcar o leche. ¿¿¡¡Qué burla de café!! ??</p><p>Ahora necesitas tener esos dos complementos también, ambos para el menú y desafortunadamente en el sistema de cobro. Originalmente, tu personal de TI hará una subclase para ambos cafés, una incluye azúcar, la otra leche. Entonces, ya que los clientes siempre están en lo correcto, uno de ellos dice estas temidas palabras:</p><p><em>"¿Me puede dar un café con leche y azúcar, por favor?"</em></p><h3 id=""><strong>???</strong></h3><p>Ahí va tu sistema de cobro riéndose en tu cara otra vez. Bueno, regresemos al pizarrón...</p><p>El personal de TI entonces añade café con leche y azúcar como otra subclase para cada clase padre de café. El resto del mes todo marcha sobre ruedas, la gente hace fila para beber tu café, ¿¿En realidad estás ganando dinero??</p><p>¡Pero espera, hay más!</p><p>El mundo en tu contra otra vez. Un competidor abre del otro lado de la calle, no con solo 4 tipos de café, ¡sino más de 10 complementos también!</p><p>Compras todos esos y más, para vender mejor café, y solo entonces recuerdas que olvidaste actualizar ese maldito sistema de cobro. Es muy posible que no puedas hacer el numero infinito de subclases para cada una de todas las combinaciones de todos los aditivos, con las nuevas mezclas de café también. Sin mencionar, el tamaño del sistema final.</p><p>Es tiempo de invertir en un sistema de cobro apropiado. Encuentras un nuevo personal de TI, quienes sí saben lo que están haciendo y te dicen:</p><p><em><em><em><em><em><em>“</em></em></em></em></em>Esto sería mucho más fácil y pequeño si se usa el patrón decorador.<em><em><em><em><em>”</em></em></em></em></em></em></p><h3 id="-qu-demonios-es-eso"><strong>¿Qué demonios es eso?</strong></h3><p>El patrón de diseño decorador cae en la categoría estructural, que lidia con la estructura real de una clase, ya sea por herencia, composición o ambos. La meta de este diseño es modificar la funcionalidad de un objeto en tiempo de ejecución. Esto es uno de otros muchos patrones de diseño que utiliza clases abstractas e interfaces con composición para obtener el resultado deseado.</p><p>Démosles la oportunidad a las matemáticas (¿temor?) para poner esto en perspectiva.</p><p>Digamos que hay 4 mezclas de café y 10 complementos. Si nos atoramos con la generación de subclases para cada diferente combinación de todos los complementos para un tipo de café. Eso es:</p><p>(10–1) ² = 9² = 81 subclases</p><p>Restamos 1 al 10, ya que no puedes combinar un complemento con otro del mismo tipo, azúcar con azúcar suena estúpido. Y eso es para una sola mezcla de café. ¡Multiplica ese <strong>81 por 4</strong> y obtendrás la enorme cantidad de <strong>324</strong> subclases diferentes! Piensa en todo el código que se tendría que escribir...</p><p>Pero con el patrón decorador se requerirán solo 16 clases en este escenario. ¿Quieres apostar?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-class-diagram.png" class="kg-image" alt="decorator-class-diagram" width="600" height="400" loading="lazy"><figcaption>Diagrama de clase del patrón de diseño Decorador</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-coffee-class-diagram.png" class="kg-image" alt="decorator-coffee-class-diagram" width="600" height="400" loading="lazy"><figcaption>Diagrama de clase correspondiente al escenario de la cafetería</figcaption></figure><p>Si trazamos nuestro escenario según el diagrama de clase anterior, obtenemos 4 clases para las 4 mezclas de café, 10 para cada aditivo y 1 para el componente abstracto y una más para el decorador abstracto. ¡Ves! ¡16! ¡Ahora dame esos $100! (Solo bromeo, pero no te los rechazaría si me los dieras... solo digo)</p><p>Como puedes ver arriba, al igual que las mezclas concretas de café son subclases de la clase abstracta de bebida, la clase abstracta AddOn también hereda sus métodos de ella. Los complementos, que son sus subclases, a la vez heredan cualquier nuevo método para añadir funcionalidad al objeto base cuando sea necesario.</p><p>Vamos al código para ver este patrón en uso.</p><p>Primero haremos la clase abstracta de bebida, esa que todas las diferentes mezclas de café heredarán:</p><pre><code class="language-java">public abstract class Beverage {
	private String description;
    
	public Beverage(String description) {
		super();
		this.description = description;
	}
    
	public String getDescription() {
		return description;
	}
    
	public abstract double cost();
}</code></pre><p>Entonces añadimos ambas mezclas de café concretas.</p><pre><code class="language-java">public class HouseBlend extends Beverage {
	public HouseBlend() {
		super(“House blend”);
	}

	@Override
	public double cost() {
		return 250;
	}
}

public class DarkRoast extends Beverage {
	public DarkRoast() {
		super(“Dark roast”);
	}

	@Override
	public double cost() {
		return 300;
	}
}</code></pre><p>La clase abstracta de AddOn también hereda de la clase abstracta Beverage (más sobre esto abajo).</p><pre><code class="language-java">public abstract class AddOn extends Beverage {
	protected Beverage beverage;

	public AddOn(String description, Beverage bev) {
		super(description);
		this.beverage = bev;
	}

	public abstract String getDescription();
}</code></pre><p>Y ahora la implementación concreta de esta clase abstracta:</p><pre><code class="language-java">public class Sugar extends AddOn {
	public Sugar(Beverage bev) {
		super(“Sugar”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Mocha”;
	}

	@Override
	public double cost() {
		return beverage.cost() + 50;
	}
}

public class Milk extends AddOn {
	public Milk(Beverage bev) {
		super(“Milk”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Milk”;
	}

	@Override  public double cost() {
		return beverage.cost() + 100;
	}
}</code></pre><p>Como puedes ver arriba, podemos pasar cualquier subclase de Beverage a cualquier subclase de AddOn, y obtener el costo añadido, así como la descripción actualizada. Y, ya que la clase AddOn es esencialmente de tipo Beverage, podemos pasar un AddOn dentro de otro AddOn. De esta forma, podemos añadir cualquier número de complementos a una mezcla de café en específico.</p><p>Ahora escribimos algo de código para probar esto.</p><pre><code class="language-java">public class CoffeeShop {
	public static void main(String[] args) {
		HouseBlend houseblend = new HouseBlend();
		System.out.println(houseblend.getDescription() + “: “ + houseblend.cost());

		Milk milkAddOn = new Milk(houseblend);
		System.out.println(milkAddOn.getDescription() + “: “ + milkAddOn.cost());

		Sugar sugarAddOn = new Sugar(milkAddOn);
		System.out.println(sugarAddOn.getDescription() + “: “ + sugarAddOn.cost());
	}
}</code></pre><p>El resultado final es:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-final.PNG" class="kg-image" alt="decorator-final" width="600" height="400" loading="lazy"><figcaption>P.D. esto está en rupias de Sri Lanka</figcaption></figure><p>¡Funciona! Somos capaces de añadir más de un complemento a una mezcla de café y actualizar su costo final y descripción exitosamente, sin la necesidad de hacer una cantidad infinita de subclases para cada combinación de complementos para todas las mezclas de café.</p><p>Finalmente, a la última categoría.</p><h2 id="tipo-3-de-comportamiento-el-patr-n-de-dise-o-de-comandos"><strong>Tipo 3: De comportamiento - El patrón de diseño de Comandos</strong></h2><p>Un patrón de diseño de comportamiento se enfoca en como las clases y objetos se comunican entre ellas. El principal enfoque del patrón de comando es inculcar un menor grado de acoplamiento (también conocido como acoplamiento débil) entre las partes involucradas (léase: clases).</p><p><em><em><em><em><em><em>Uhhhh… </em></em></em></em></em>¿Qué es eso?</em></p><p>El acoplamiento es la forma en la que dos (o más) clases interactúan entre ellas. El escenario ideal cuando estas clases interactúan es que no dependan fuertemente una de otra. Eso es acoplamiento débil. Así que, una mejor definición para el acoplamiento débil sería: clases que están interconectadas, haciendo el menor uso entre ellas.</p><p>La necesidad de este patrón surgió cuando las peticiones necesitaban ser enviadas sin saber conscientemente que es lo que se pide o quien es el receptor.</p><p>En este patrón, la invocación de la clase esta desacoplada de la clase que realmente ejecuta una acción. La clase invocadora solo tiene el método invocable execute, el cuál corre el comando necesario, cuando el cliente lo solicita.</p><p>Veamos un ejemplo básico de la vida real ordenando un platillo en un restaurant elegante. Como el flujo va, tú le das tu orden (comando) al mesero (invocador), quien entonces entrega al chef (receptor), y es así como obtienes tu comida. Puede sonar sencillo... pero es algo aburrido de codificar.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/07/chain-of-command-be-like-pop-snoke-im-going-to-27790631.png" class="kg-image" alt="chain-of-command-be-like-pop-snoke-im-going-to-27790631" width="600" height="400" loading="lazy"></figure><p>La idea es bastante sencilla, pero la programación da mil vueltas.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/07/command-class-diagram.PNG" class="kg-image" alt="command-class-diagram" width="600" height="400" loading="lazy"><figcaption>Diagrama de clase del patrón de diseño Comando</figcaption></figure><p>El flujo de operación del lado técnico es: haces un comando concreto, el cual implementa la interfaz Command, pidiendo al receptor que complete una acción, y envía el comando al invocador. El invocador es la persona que sabe cuándo dar el comando. El chef es el único que sabe qué hacer cuando se le da una orden o un comando especifico. Entonces, cuando el método "execute" del invocador es ejecutado, este a su vez, hace que se ejecute el método "execute" del objeto del comando en el receptor, completando así las acciones necesarias.</p><p><strong>Lo que necesitamos para implementarlo es:</strong></p><ol><li>Una interfaz Command</li><li>Una clase Order que implemente la interfaz Command</li><li>Una clase Waiter (invocador)</li><li>Una clase Chef (receptor)</li></ol><p>Entonces, el código es el siguiente:</p><h3 id="chef-el-receptor"><strong>Chef, el receptor</strong></h3><pre><code class="language-java">public class Chef {
	public void cookPasta() {
		System.out.println(“Chef is cooking Chicken Alfredo…”);
	}

	public void bakeCake() {
		System.out.println(“Chef is baking Chocolate Fudge Cake…”);
	}
}</code></pre><h3 id="command-la-interfaz"><strong>Command, la interfaz</strong></h3><pre><code class="language-java">public interface Command {
	public abstract void execute();
}</code></pre><h3 id="order-el-comando-concreto"><strong>Order, el comando concreto</strong></h3><pre><code class="language-java">public class Order implements Command {
	private Chef chef;
	private String food;

	public Order(Chef chef, String food) {
		this.chef = chef;
		this.food = food;
	}

	@Override
	public void execute() {
		if (this.food.equals(“Pasta”)) {
			this.chef.cookPasta();
		} else {
			this.chef.bakeCake();
		}
	}
}</code></pre><h3 id="waiter-el-invocador"><strong>Waiter, el invocador</strong></h3><pre><code class="language-java">public class Waiter {
	private Order order;

	public Waiter(Order ord) {
		this.order = ord;
	}

	public void execute() {
		this.order.execute();
	}
}</code></pre><h2 id="t-el-cliente"><strong>Tú, el cliente</strong></h2><pre><code class="language-java">public class Client {
	public static void main(String[] args) {
		Chef chef = new Chef();
        
		Order order = new Order(chef, “Pasta”);
		Waiter waiter = new Waiter(order);
		waiter.execute();

		order = new Order(chef, “Cake”);
		waiter = new Waiter(order);
		waiter.execute();
	}
}</code></pre><p>Como puedes ver arriba, la clase Client hace una Orden y establece al Chef como receptor. La Orden es enviada al Mesero, quien sabrá cuando ejecutar la Orden (por ejemplo, cuando dar la orden a cocinar al chef). Cuando el invocador es ejecutado, el método "execute" de la clase Order es ejecutado en el receptor (por ejemplo, al chef se le da una orden para cocinar pasta u hornear un pastel).</p><h2 id="repaso-r-pido"><strong>Repaso rápido</strong></h2><p>En este artículo hablamos de:</p><ol><li>Qué es realmente un patrón de diseño</li><li>Los diferentes tipos de patrones de diseño y por qué son diferentes</li><li>Un patrón de diseño básico o común de cada tipo</li></ol><p>Espero que te haya sido de ayuda.</p><p>Encuentra el repositorio del código de este artículo <a href="https://github.com/samsam-026/Design_Patterns">aquí</a>.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 4 patrones de diseño que deberías saber para desarrollo web: Observador, Singleton, estrategia, y decorador ]]>
                </title>
                <description>
                    <![CDATA[ ¿Alguna vez has estado en un equipo donde necesitas empezar un proyecto desde el principio? Ese es usualmente el caso en muchas start-ups y otras compañías pequeñas. Hay demasiados lenguajes de programación distintos, arquitecturas, y otras preocupaciones que puede ser difícil decidir por dónde empezar. Ahí es donde los patrones ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/4-patrones-de-diseno-que-deberias-saber-para-desarrollo-web-observador-singleton-estrategia-y-decorador/</link>
                <guid isPermaLink="false">642c09decbd6cf076f06b3ef</guid>
                
                    <category>
                        <![CDATA[ Patrones de Diseño ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elias Ezequiel Pereyra Gomez ]]>
                </dc:creator>
                <pubDate>Fri, 21 Apr 2023 18:37:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/04/design-patterns.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/4-design-patterns-to-use-in-web-development/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">4 Design Patterns You Should Know for Web Development: Observer, Singleton, Strategy, and Decorator</a>
      </p><p>¿Alguna vez has estado en un equipo donde necesitas empezar un proyecto desde el principio? Ese es usualmente el caso en muchas start-ups y otras compañías pequeñas.</p><p>Hay demasiados lenguajes de programación distintos, arquitecturas, y otras preocupaciones que puede ser difícil decidir por dónde empezar. Ahí es donde los patrones de diseño entran.</p><p>Un patrón de diseño es como una plantilla para tu proyecto. Usa ciertas convenciones y puedes esperar un comportamiento de tipo específico. Estos patrones fueron inventados según las diversas experiencias de los desarrolladores, así que son realmente como distintos conjuntos de mejores prácticas.</p><p>Y tú y tu equipo deciden cuál conjunto de mejores prácticas es la más útil para su proyecto. Según el patrón de diseño que elijas, todos empezarán a tener expectativas de lo que el código debería estar haciendo y qué vocabulario todos estarán usando.</p><p>Los Patrones de Diseño de Programación pueden ser usados en todos los lenguajes de programación y pueden ser usados para coincidir en cualquier proyecto porque te dan solamente un esquema general de una solución.</p><p>Hay 23 patrones oficiales del libro <em>Design Patterns - Elements of Reusable Object-Oriented Software</em>, el cual es considerado uno de los libros más influyentes en la teoría de orientación a objetos y desarrollo de software.</p><p>En este artículo, voy a cubrir cuatro de esos patrones de diseño para darte una idea de lo que son algunos de los patrones y cuando los usarías.</p><h2 id="el-patr-n-de-dise-o-singleton"><strong>El patrón de diseño singleton</strong></h2><p>El patrón singleton solamente permite a una clase u objeto tener una sola instancia y usa una variable global para almacenar esa instancia. Puedes usar carga perezosa para asegurar que hay solamente una instancia de la clase, porque creará la clase solamente cuando lo necesites.</p><p>Eso previene a múltiples instancias de estar activas al mismo tiempo, lo cual podría causar errores raros. La mayoría de las veces esto se implementa en el constructor. El objetivo del patrón singleton es típicamente regular el estado global de una aplicación.</p><p>Un ejemplo de un singleton es que probablemente uses todo el tiempo tu registrador. </p><p>Si trabajas con algunos de los frameworks de front-end como React o Angular, sabes todo lo tramposo que puede ser manejar registros viniendo de múltiples componentes. Este es un gran ejemplo para los singletons en acción porque nunca quieres más de una instancia de un objeto registrador, especialmente si estás usando algún tipo de herramienta de rastreo de error.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class RegistradorComida {
  constructor() {
    this.registroComida = []
  }
    
  registrar(orden) {
    this.registroComida.push(orden.itemComida)
    // hacer un código elegante para enviar este registro a algún lugar
  }
}

// este es el singleton
class SingletonRegistradorComida {
  constructor() {
    if (!SingletonRegistradorComida.instance) {
      SingletonRegistradorComida.instance = new RegistradorComida()
    }
  }
  
  getInstanciaRegistradorComida() {
    return SingletonRegistradorComida.instance
  }
}

module.exports = SingletonRegistradorComida</code></pre><figcaption>Un ejemplo de la clase singleton</figcaption></figure><p>Ahora, no tienes que preocuparte de perder registros de múltiples instancias porque solamente tienes una en tu proyecto. Así que cuando quieras registrar la comida que ha sido ordenada, puedes usar la misma instancia de <em>RegistradorComida</em> &nbsp;a lo largo de múltiples archivos o componentes.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const RegistradorComida = require('./RegistradorComida')

const registradorComida = new RegistradorComida().getInstanciaRegistradorComida()

class Cliente {
  constructor(orden) {
    this.precio = orden.precio
    this.comida = orden.itemComida
    registradorComida.registrar(orden)
  }
  
  // otras cosas geniales realizando para el cliente
}

module.exports = Cliente</code></pre><figcaption>Un ejemplo de una clase Cliente usando el singleton</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const RegistradorComida = require('./RegistradorComida')

const registradorComida = new RegistradorComida().getInstanciaRegistradorComida()

class Restaurante {
  constructor(inventario) {
    this.cantidad = inventario.cuenta
    this.comida = inventario.itemComida
    registradorComida.registrar(inventario)
  }
  
  // otras cosas realizando en el restaurante
}

module.exports = Restaurante</code></pre><figcaption>Un ejemplo de la clase Restaurante usando el mismo singleton como la clase Cliente</figcaption></figure><p>Con este patrón singleton en lugar, no tienes que preocuparte sobre obtener los registros del archivo principal. Puedes obtenerlos de cualquier lugar en la base de tu código e irán todos a la misma instancia exacta del registrador, lo cual significa que ninguno de tus registros deberían perderse debido a nuevas instancias.</p><h2 id="el-patr-n-de-dise-o-estrategia"><strong>El patrón de diseño estrategia</strong></h2><p>El patrón estrategia es como una versión avanzada de una sentencia if else. Es básicamente donde haces una interfaz para un método que tienes en tu clase base. Esta interfaz es usada luego para encontrar la implementación correcta de ese método que debería ser usado en una clase derivada. La implementación, en este caso, será decidida en el tiempo de ejecución basado en el cliente.</p><p>Este patrón es increíblemente útil en situaciones donde tienes métodos requeridos y opcionales para una clase. Algunas instancias de esa clase no necesitarán los métodos opcionales, y eso causa un problema para soluciones de herencia. Podrías usar interfaces para los métodos opcionales, pero después tendrías que escribir la implementación cada vez que uses la clase, ya que no habría una implementación por defecto.</p><p>Ahí es donde el patrón estrategia nos salva. En vez de que el cliente busque una implementación, lo delega a la interfaz de estrategia y la estrategia encuentra la implementación correcta. Un uso común para esto son los sistemas de procesamiento de pago.</p><p>Podrías tener un carrito de compras que solamente permita a los clientes pagar con sus tarjetas de crédito, pero perderás clientes que quieran usar otros métodos de pago.</p><p>El patrón de diseño estrategia nos permite desacoplar los métodos de pago desde el proceso de pago, lo cual significa que podemos agregar o actualizar estrategias sin cambiar ningún código en el carrito de compras o en el proceso de pago.</p><p>Aquí hay un ejemplo de una implementación del patrón estrategia usando el ejemplo del método de pago.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">class EstrategiaMetodoPago {

  const tipoInfoCliente = {
    pais: string
    direccionEmail: string
    nombre: string
    numeroCuenta?: number
    direccion?: string
    numeroTarjeta?: number
    ciudad?: string
    numeroRuta?: number
    estado?: string
  }
  
  static CuentaBanco(infoCliente: tipoInfoCliente) {
    const { nombre, numeroCuenta, numeroRuta } = infoCliente
    // hace cosas para obtener el pago
  }
  
  static BitCoin(infoCliente: tipoInfoCliente) {
    const { direccionEmail, numeroCuenta } = infoCliente
    // hace cosas para obtener el pago
  }
  
  static TarjetaCredito(infoCliente: tipoInfoCliente) {
    const { nombre, tarjetaCredito, direccionEmail } = infoCliente
    // hace cosas para obtener el pago
  }
  
  static CorreoEntrante(infoCliente: tipoInfoCliente) {
    const { nombre, direccion, ciudad, estado, pais } = infoCliente
    // hace cosas para obtener el pago
  }
  
  static PayPal(infoCliente: tipoInfoCliente) {
    const { direccionEmail } = infoCliente
    // hace cosas para obtener el pago
  }
}</code></pre><figcaption>Un ejemplo de la implementación del patrón strategy</figcaption></figure><p>Para implementar nuestra estrategia del método de pago, hicimos una sola clase con múltiples métodos estáticos. Cada método toma el mismo parámetro, <em>infoCliente</em>, y ese parámetro tiene un tipo definido de <em>tipoInfoCliente</em>. (Hey, todos ustedes desarrolladores de TypeScript!??) Toma nota de que cada método tiene su propia implementación y usa valores distintos del <em>infoCliente</em>. </p><p>Con el patrón estrategia, también puedes cambiar dinámicamente la estrategia que es usada en tiempo de ejecución. Eso significa que serás capaz de cambiar la estrategia, o la implementación del método, que está siendo usado según la entrada de usuario o el entorno donde la app está corriendo.</p><p>También puedes establecer una implementación por defecto en un simple archivo <em>config.json</em>, así:</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "metodoPago": {
    "estrategia": "PayPal"
  }
}</code></pre><figcaption>config.json para establecer la implementación por defecto del metodoPago a "PayPal" en tiempo de ejecutación</figcaption></figure><p>Cuando sea que el cliente comience a ir a través del proceso de pago en tu sitio web, el método de pago por defecto que encuentren será la implementación de PayPal el cual viene del <em>config.json</em>. Esto podría fácilmente ser actualizado si el cliente selecciona un método de pago diferente.</p><p>Ahora crearemos un archivo para nuestro proceso de pago.</p><pre><code class="language-javascript">const EstrategiaMetodoPago = require('./EstrategiaMetodoPago')
const config = require('./config')

class Pago {
  constructor(estrategia='TarjetaCredito') {
    this.estrategia = EstrategiaMetodoPago[estrategia]
  }
  
  // hacer algo de código elegante aquí y obtener entrada del usuario y método de pago
  
  cambiarEstrategia(nuevaEstrategia) {
    this.estrategia = EstrategiaMetodoPago[nuevaEstrategia]
  }
  
  const entradaUsuario = {
    nombre: 'Malcolm',
    numeroTarjeta: 3910000034581941,
    direccionEmail: 'mac@gmailer.com',
    pais: 'US'
  }
  
  const estrategiaSeleccionada = 'Bitcoin'
  
  cambiarEstrategia(estrategiaSeleccionada)
  
  postPago(entradaUsuario) {
    this.estrategia(entradaUsuario)
  }
}

module.exports = new Pago(config.metodoPago.estrategia)</code></pre><p>Esta clase <em>Pago</em> es donde el patrón estrategia viene a mostrarse. Importamos un par de archivos, así tenemos las estrategias de método de pago disponibles y la estrategia por defecto del <em>config</em>.</p><p>Entonces creamos la clase con el constructor y un valor de reserva para la <em>estrategia</em> por defecto en caso de que uno no haya sido puesto en el <em>config</em>. Después asignamos el valor <em>estrategia</em> a una variable de estado local.</p><p>Un método importante que necesitamos implementar en nuestra clase <em>Pago</em> es la habilidad de cambiar la estrategia de pago. Un cliente podría cambiar el método de pago que quieran usar y necesitarás ser capaz de manejar eso. Para eso está el método <em>cambiarEstrategia</em>.</p><p>Después que hayas hecho algún código elegante y hayas obtenido todas las entradas del cliente, entonces puedes actualizar la estrategia de pago inmediatamente según su entrada y pone la <em>estrategia</em> dinámicamente antes de que el pago sea enviado para ser procesado.</p><p>En algún punto podrías necesitar agregar más métodos de pago a tu carrito de compras y todo lo que tendrás que hacer es agregarlo a la clase <em>EstrategiaMetodoPago</em>. Estará disponible al instante en cualquier lugar donde la clase sea usada.</p><p>El patrón de diseño estrategia es poderoso cuando lidias con métodos que tienen múltiples implementaciones. Podría sentirse como que estás usando una interfaz, pero no tienes que escribir una implementación para el método cada vez que lo llames en una clase distinta. Te da más flexibilidad que las interfaces.</p><h2 id="el-patr-n-de-dise-o-observador"><strong>El patrón de diseño observador</strong></h2><p>Si alguna vez has usado el patrón MVC, ya has usado el patrón de diseño observador. La parte Modelo es como un sujeto y la parte Vista es como un observador de ese sujeto. Tu sujeto sostiene todos los datos y el estado de esos datos. Después tienes los observadores, como componentes distintos, que obtendrá esos datos del sujeto cuando los datos hayan sido actualizados. </p><p>El objetivo del patrón de diseño observador es crear la relación uno-a-muchos entre el sujeto y todos los observadores que esperan recibir datos para que sean actualizados. Así que en cualquier tiempo que el estado del sujeto cambie, todos los observadores serán notificados y actualizados instantáneamente.</p><p>Algunos ejemplos de cuando usarías este patrón incluyen: enviar notificaciones de usuario, actualizar, filtros, y manejar suscriptores.</p><p>Digamos que tienes una aplicación de una sola página que tiene tres características de listas despegables que son dependientes de la selección de una categoría de un nivel superior del despegable. Esto es común en muchos sitios de compras, como Depósito de Casa. Tienes un montón de filtros en la página que son dependientes del valor de un filtro de nivel superior.</p><p>El código para el despegable de nivel superior podría parecerse algo así:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class CategoriaDespegable {
  constructor() {
    this.categorias = ['accesorios', 'puertas', 'herramientas']
    this.suscriptor = []
  }
  
  // pretén que hay algún código elegante aquí
  
  suscribir(observador) {
    this.suscriptor.push(observador)
  }
  
  alCambiar(categoriaSeleccionada) {
    this.suscriptor.forEach(observador =&gt; observador.actualizar(categoriaSeleccionada))
  }
}</code></pre><figcaption>El sujeto que actualiza los observadores</figcaption></figure><p>Este archivo <em>CategoriaDespegable</em> es una simple clase con un constructor que inicializa las opciones de categoría que tenemos disponibles en el despegable. Este es el archivo que manejarías recuperando una lista del back-end o cualquier tipo de ordenación que quieras hacer antes de que el usuario vea las opciones.</p><p>El método <em>suscribir</em> es como cada filtro creado con esta clase recibirá actualizaciones sobre el estado del observador. </p><p>El método <em>alCambiar</em> es cómo mandamos notificaciones a todos los suscriptores de que un cambio de estado ha sucedido en el observador que está escuchando. Solo iteramos a través de todos los suscriptores y llamamos a su método <em>actualizar</em> con el <em>categoriaSeleccionada</em>. </p><p>El código para los otros filtros podría parecerse así:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class FiltrarDespegable {
  constructor(tipoFiltro) {
    this.tipoFiltro = tipoFiltro
    this.items = []
  }
  
  // más código elegante aquí; tal vez hacer una llamada a la API para obtener una lista de items según el tipo de filtro
  
  actualizar(categoria) {
    fetch('https://example.com')
      .then(res =&gt; this.items(res))
  }
}</code></pre><figcaption>A observador potencial del sujeto</figcaption></figure><p>Este archivo <em>FiltroDespegable</em> es otra simple clase que representa todos los despegables potenciales que podríamos usar en una página. Cuando una nueva instancia de esta clase es creada, un <em>tipoFiltro</em> necesita ser pasado. Esto podría ser usado para hacer llamadas específicas a la API para tener la lista de items. </p><p>El método <em>actualizar</em> es una implementación de lo que puedes hacer con la nueva categoría una vez que ha sido enviado desde el observador.</p><p>Ahora veremos qué significa usar estos archivos con el patrón observador:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const CategoriaDespegable = require('./CategoriaDespegable')
const FiltroDespegable = require('./FiltroDespegable')

const categoriaDespegable = new CategoriaDespegable() 

const despegableColores = new FiltroDespegable('colores')
const despegablePrecio = new FiltroDespegable('precio')
const despegableMarca = new FiltroDespegable('marca')

categoriaDespegable.suscribir(despegableColores)
categoriaDespegable.suscribir(despegablePrecio)
categoriaDespegable.suscribir(despegableMarca)</code></pre><figcaption>Un ejemplo del patrón observador en acción</figcaption></figure><p>Lo que este archivo nos muestra es que tenemos 3 despegables que son suscriptores a la categoría observable despegable. Luego suscribimos a cada uno de estos despegables al observador. Cuando sea que la categoría del observador es actualizada, enviará el valor a cada suscriptor el cual actualizará las listas despegables individuales instantáneamente.</p><h2 id="el-patr-n-de-dise-o-decorador"><strong>El patrón de diseño decorador</strong></h2><p>Usar el patrón de diseño decorador es bastante simple. Puedes tener una clase base con métodos y propiedades que están presentes cuando haces un nuevo objeto con la clase. Ahora, digamos que tienes algunas instancias de la clase que necesita métodos o propiedades que no vinieron de la clase base.</p><p>Puedes agregar esos métodos y propiedades extras a la clase base, pero eso podría arruinar tus otras instancias. Podrías inclusive hacer sub-clases para mantener métodos y propiedades específicos que necesitas que no puedes poner en tu clase base.</p><p>Cualquiera de esos enfoques resolverán tu problema,pero son torpes e ineficientes. Ahí es donde el patrón decorador interviene. En vez de hacer feo a tu código base solo para agregar un poco de cosas a una instancia de un objeto, puedes agregar esas cosas específicas directamente a la instancia. </p><p>Así que si necesitas agregar una nueva propiedad que mantiene el precio de un objeto, puedes usar el patrón decorador para agregarlo directamente a esa instancia de objeto particular y no afectará ninguna de las otras instancias de ese objeto de clase.</p><p>¿Alguna vez has ordenado comida en línea? Entonces probablemente has encontrado el patrón decorador. Si vas a pedir un sandwich y quieres agregar coberturas especiales, el sitio web no agrega esas coberturas a cada instancia de sandwich que los usuarios actuales están tratando de ordenar.</p><p>Aquí hay un ejemplo de una clase cliente:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class Cliente {
  constructor(balance=20) {
    this.balance = balance
    this.itemsComida = []
  }
  
  comprar(comida) {
    if (comida.precio) &lt; this.balance {
      console.log('deberías comprarlo')
      this.balance -= comida.precio
      this.itemsComida.push(comida)
    }
    else {
      console.log('tal vez deberías comprar otra cosa')
    }
  }
}

module.exports = Cliente</code></pre><figcaption>Un ejemplo de una clase Cliente</figcaption></figure><p>Y aquí hay un ejemplo de la clase Sandwich:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class Sandwich {
  constructor(tipo, precio) {
    this.tipo = tipo
    this.precio = precio
  }
  
  ordenar() {
    console.log(`Ordenaste un sandwich ${this.tipo} por $ ${this.precio}.`)
  }
}

class SandwichDeLujo {
  constructor(baseSandwich) {
    this.tipo = `${baseSandwich.tipo} Lujoso`
    this.precio = baseSandwich.precio + 1.75
  }
}

class SandwichExquisito {
  constructor(baseSandwich) {
    this.tipo = `${baseSandwich.tipo} Exquisito `
    this.precio = baseSandwich.precio + 10.75
  }
  
  ordenar() {
    console.log(`Ordenaste un sandwich ${this.tipo}. Tiene todo lo que necesitas para ser feliz por muchos días.`)
  }
}

module.exports = { Sandwich, SandwichDeLujo, SandwichExquisito }</code></pre><figcaption>Un ejemplo de una clase sandwich</figcaption></figure><p>En esta clase sandwich es donde se usa el patrón decorador. Tenemos una clase base <em>Sandwich</em> que pone las reglas de lo que sucede cuando una sandwich regular es ordenado. Los clientes podrían querer mejorar los sandwiches y eso sólo significa un cambio de ingrediente y de precio.</p><p>Solo quisiste agregar la funcionalidad incrementar el precio y actualizar el tipo de sandwich para el <em>SandwichDeLujo</em> sin cambiar la forma cómo es ordenado. Aunque podrías necesitar una orden distinta para un <em>SandwichExiquisito</em> porque hay un cambio drástico en la calidad de los ingredientes.</p><p>El patrón decorador te permite cambiar dinámicamente la clase base sin afectarlo o a ninguna de las otras clases. No tienes que preocuparte sobre implementar funciones que no conoces, como con interfaces, y no tienes que incluir propiedades que no usarás en cada clase.</p><p>Ahora iremos sobre un ejemplo donde esta clase se instancia como si el cliente estuviera haciendo un pedido de un sandwich.</p><pre><code class="language-javascript">const { Sandwich, SandwichDeLujo, SandwichExquisito } = require('./Sandwich')
const Cliente = require('./Cliente')

const cli1 = new Cliente(57)

const sandwhichPavo = new Sandwich('Pavo', 6.49)
const sandwichBLT = new Sandwich('BLT', 7.55)

const sandwichBltDeLujo = new SandwichDeLujo(sandwichBLT)
const sandwichPavoExquisito = new SandwichExquisito(sandwichPavo)

cust1.comprar(sandwichPavo)
cust1.comprar(sandwichBLT)</code></pre><h2 id="pensamientos-finales"><strong>Pensamientos finales</strong></h2><p>Solía pensar que los patrones de diseño eran estas guías difíciles y extravagantes de desarrollo de software. ¡Luego descubrí que los uso todo el tiempo!</p><p>Unos de los patrones que cubrí son usados en muchísimas aplicaciones que te dejaría boquiabierto. Son sólo teorías al fin y al cabo. Depende de nosotros como desarrolladores usar esa teoría de manera que haga a nuestras aplicaciones fáciles de implementar y de mantener.</p><p>¿Has usado algunos de los otros patrones de diseño para tus proyectos? La mayoría de los lugares usualmente toman un patrón de diseño para sus proyectos y se apegan a él, así que me gustaría escuchar de todos ustedes sobre cuál usan.</p><p>Gracias por leer. Deberías seguirme en Twitter porque usualmente posteo cosas útiles / entretenidas: <a href="https://twitter.com/FlippedCoding">@FlippedCoding</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ El patrón modelo-vista-controlador:  Arquitectura y frameworks explicados ]]>
                </title>
                <description>
                    <![CDATA[ El patrón de arquitectura MVC convierte el desarrollo de aplicaciones complejas en un proceso mucho más manejable. Permite a varios desarrolladores trabajar simultáneamente en la aplicación. Cuando me entere por primera vez de los patrones de MVC, me intimidó toda la terminología. Y más aún cuando empece a aplicar estos ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/el-modelo-de-arquitectura-view-controller-pattern/</link>
                <guid isPermaLink="false">60a73c0df9becc08c7a3777d</guid>
                
                    <category>
                        <![CDATA[ Patrones de Diseño ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rafael D. Hernandez ]]>
                </dc:creator>
                <pubDate>Mon, 28 Jun 2021 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/06/BG4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>El patrón de arquitectura MVC convierte el desarrollo de aplicaciones complejas en un proceso mucho más manejable. Permite a varios desarrolladores trabajar simultáneamente en la aplicación.</p><p>Cuando me entere por primera vez de los patrones de MVC, me intimidó toda la terminología. Y más aún cuando empece a aplicar estos conceptos a una aplicación real.</p><p>Al dar un paso atrás para centrarse en lo que MVC es y lo que puede lograr, es mucho más fácil entender y aplicar el patrón a cualquier aplicación web.</p><h2 id="-que-es-mvc">¿Que es MVC?</h2><p>MVC significa modelo (model) vista (view) controlador (controller). Esto es lo que significan cada uno de esos componentes.</p><ul><li><strong>Modelo</strong>: El backend que contiene toda la lógica de datos</li><li><strong>Vista</strong>: El frontend o interfaz gráfica de usuario (GUI)</li><li><strong>Controlador</strong>: El cerebro de la aplicación que controla como se muestran los datos.</li></ul><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/06/MVC3.png" class="kg-image" alt="MVC3" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/06/MVC3.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/06/MVC3.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/06/MVC3.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/2021/06/MVC3.png 2277w" sizes="(min-width: 1200px) 1200px" width="2277" height="1802" loading="lazy"><figcaption>Gráfica de patrones de arquitectura MVC</figcaption></figure><p>El concepto de MVC fue introducido por primera vez por Trygve Reenskaug, quien lo propuso como una forma de desarrollar el GUI de aplicaciones de escritorio.</p><p>Hoy en día, el patrón MVC se utiliza para aplicaciones web modernas porque permite que la aplicación sea escalable, mantenible y fácil de expandir.</p><h2 id="-por-qu-deber-as-usar-mvc">¿Por qué deberías usar MVC?</h2><p>Tres palabras: separación de preocupaciones (separation of concerns), o SoC para abreviar.</p><p>El patrón MVC te ayuda a dividir el código frontend y backend en componentes separados. De esta manera, es mucho más fácil administrar y hacer cambios a cualquiera de los lados sin que interfieran entre sí.</p><p>Pero esto es más fácil decirlo que hacerlo, especialmente cuando varios desarrolladores necesitan actualizar, modificar o depurar una aplicación completada simultáneamente.</p><h2 id="c-mo-usar-mvc">Cómo usar MVC</h2><p>Para ilustrar mejor el patrón MVC, he incluido una aplicación web que muestra cómo funcionan todos estos conceptos.</p><p>La aplicación "My Car Clicker" es una variación de una aplicación conocida como "Cat Clicker".</p><p>Estas son algunas de las principales diferencias en mi aplicación:</p><ol><li>No hay gatos, solo imágenes de carros potentes (¡lo siento, amantes de los gatos!)</li><li>Se enumeran varios modelos de automóviles</li><li>Hay varios contadores de clics</li><li>Solo muestra el coche seleccionado</li></ol><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screen-Recording-2021-04-11-at-11.31.27.07-PM.gif" class="kg-image" alt="Screen-Recording-2021-04-11-at-11.31.27.07-PM" width="600" height="400" loading="lazy"></figure><p>Ahora vamos a sumergirnos en estos tres componentes que componen el patrón de arquitectura MVC.</p><h3 id="modelo-datos-">Modelo (datos)</h3><p>El trabajo del modelo es simplemente administrar los datos. Ya sea que los datos provengan de una base de datos, una API o un objeto JSON, el modelo es responsable de administrarlos.</p><p>En la aplicación Car Clicker, el objeto modelo contiene un arreglo de objetos car con toda la información (datos) necesaria para la aplicación.</p><p>También gestiona el carro actual que se muestra con una variable que se establece inicialmente en <code>null</code>.</p><pre><code class="language-javaScript">const model = {
    currentCar: null,
    cars: [
        {
            clickCount: 0,
            name: 'Coupe Maserati',
            imgSrc: 'img/black-convertible-coupe.jpg',
        },
        {
            clickCount: 0,
            name: 'Camaro SS 1LE',
            imgSrc: 'img/chevrolet-camaro.jpg',
        },
        {
            clickCount: 0,
            name: 'Dodger Charger 1970',
            imgSrc: 'img/dodge-charger.jpg',
        },
        {
            clickCount: 0,
            name: 'Ford Mustang 1966',
            imgSrc: 'img/ford-mustang.jpg',
        },
        {
            clickCount: 0,
            name: '190 SL Roadster 1962',
            imgSrc: 'img/mercedes-benz.jpg',
        },
    ],
};</code></pre><h3 id="vistas-ui-">Vistas (UI)</h3><p>El trabajo de la vista es decidir qué verá el usuario en su pantalla y cómo.</p><p>La aplicación "Car Clicker" tiene dos vistas: carListView y CarView.</p><p>Ambas vistas tienen dos funciones críticas que definen lo que cada vista quiere inicializar y renderizar.</p><p>Estas funciones son donde la aplicación decide lo que el usuario verá y cómo.</p><h4 id="carlistview">carListView</h4><pre><code class="language-js">const carListView = {
    init() {
        // almacene el elemento DOM para un fácil acceso más tarde
        this.carListElem = document.getElementById('car-list');

        // renderizar esta vista (actualizar los elementos DOM con los valores correctos)
        this.render();
    },

    render() {
        let car;
        let elem;
        let i;
        // obtener los carros para ser renderizados desde el controlador
        const cars = controller.getCars();

        // para asegurarse de que la lista está vacía antes de renderiz
        this.carListElem.innerHTML = '';

        // bucle sobre el arreglo de carros
        for(let i = 0; i &lt; cars.length; i++) {
            // este es el carro que tenemos en bucle
            car = cars[i];

            // hacer un nuevo elemento de la lista de carros y establecer su texto
            elem = document.createElement('li');
            elem.className = 'list-group-item d-flex justify-content-between lh-condensed';
            elem.style.cursor = 'pointer';
            elem.textContent = car.name;
            elem.addEventListener(
                'click',
                (function(carCopy) {
                    return function() {
                        controller.setCurrentCar(carCopy);
                        carView.render();
                    };
                })(car)
            );
            // finalmente, agregua el elemento a la lista
            this.carListElem.appendChild(elem);
        }
    },
};</code></pre><h4 id="carview">CarView</h4><pre><code class="language-js">const carView = {
    init() {
        // almacene punteros a los elementos DOM para un fácil acceso más tarde
        this.carElem = document.getElementById('car');
        this.carNameElem = document.getElementById('car-name');
        this.carImageElem = document.getElementById('car-img');
        this.countElem = document.getElementById('car-count');
        this.elCount = document.getElementById('elCount');


        // al hacer clic, aumentar el contador del carro actual
        this.carImageElem.addEventListener('click', this.handleClick);

        // renderizar esta vista (actualizar los elementos DOM con los valores correctos)
        this.render();
    },

    handleClick() {
    	return controller.incrementCounter();
    },

    render() {
        // actualizar los elementos DOM con valores del carro actual
        const currentCar = controller.getCurrentCar();
        this.countElem.textContent = currentCar.clickCount;
        this.carNameElem.textContent = currentCar.name;
        this.carImageElem.src = currentCar.imgSrc;
        this.carImageElem.style.cursor = 'pointer';
    },
};</code></pre><h3 id="controlador-cerebro-">Controlador (Cerebro)</h3><p>La responsabilidad del controlador es extraer, modificar y proporcionar datos al usuario. Esencialmente, el controlador es el enlace entre &nbsp;y el modelo.</p><p>A través de las funciones getter y setter, el controlador extrae datos del modelo e inicializa las vistas.</p><p>Si hay alguna actualización desde las vistas, modifica los datos con una función setter.</p><pre><code class="language-js">const controller = {
    init() {
        // establecer el carro actual como el primero en la lista
        model.currentCar = model.cars[0];

        // indicar a las vistas que inicialicen
        carListView.init();
        carView.init();
    },

    getCurrentCar() {
    	return model.currentCar;
    },

    getCars() {
    	return model.cars;
    },

    // establecer el carro seleccionado actualmente en el objeto que se pasa en
    setCurrentCar(car) {
    	model.currentCar = car;
    },

    // incrementar el contador para el coche seleccionado actualmente
    incrementCounter() {
        model.currentCar.clickCount++;
        carView.render();
    },
};

controller.init();</code></pre><h2 id="mvc-frameworks">MVC Frameworks</h2><p>JavaScript ha crecido en popularidad, y se ha apoderado del backend en los últimos años. Cada vez más aplicaciones JavaScript &nbsp;han optado por el patrón de arquitectura MVC de una manera u otra.</p><p>Los frameworks van y vienen, pero lo que ha sido constante son los conceptos tomados del patrón de arquitectura MVC.</p><p>Algunos de los primeros frameworks que aplicaron estos conceptos fueron <strong>KnockoutJS</strong>, <strong>Django</strong> y <strong>Ruby on Rails</strong>.</p><h2 id="conclusion">Conclusion</h2><p>El concepto más atractivo del patrón MVC es la separación de preocupaciones.</p><p>Las aplicaciones web modernas son muy complejas, y hacer un cambio a veces puede ser un gran dolor de cabeza.</p><p>Administrar el frontend y el backend en componentes separados más pequeños permite que la aplicación sea escalable, mantenible y fácil de expandir.</p><p><em>**Si quieres echar un vistazo a la aplicación Car Clicker, el código está disponible en </em><a href="https://github.com/RafaelDavisH/car-clicker/blob/main/README.md"><em>GitHub</em></a><em> </em>o echa un vistazo a la versión en vivo<em> </em><a href="https://rafaeldavish.github.io/car-clicker/"><em>aquí</em></a><em>.** </em></p><p>? ¡Gracias por leer hasta aquí! ?</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
