<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Patron de diseño &#8211; Oscar Blancarte &#8211; Software Architecture</title>
	<atom:link href="https://www.oscarblancarteblog.com/tag/patron-de-diseno/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.oscarblancarteblog.com</link>
	<description>Software Architect &#38; FullStack developer</description>
	<lastBuildDate>Sun, 12 Jul 2020 17:18:35 +0000</lastBuildDate>
	<language>es-MX</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.15</generator>

<image>
	<url>https://www.oscarblancarteblog.com/wp-content/uploads/2019/03/cropped-ob-32x32.png</url>
	<title>Patron de diseño &#8211; Oscar Blancarte &#8211; Software Architecture</title>
	<link>https://www.oscarblancarteblog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">89905023</site>	<item>
		<title>Data Access Object (DAO) Pattern</title>
		<link>https://www.oscarblancarteblog.com/2018/12/10/data-access-object-dao-pattern/</link>
					<comments>https://www.oscarblancarteblog.com/2018/12/10/data-access-object-dao-pattern/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Mon, 10 Dec 2018 17:00:35 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[Arquitectura de software]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=2484</guid>

					<description><![CDATA[<p>Prácticamente todas las aplicaciones de hoy en día, requiere acceso al menos a una fuente de datos, dichas fuentes son por lo general base de datos relacionales, por lo que muchas veces no tenemos problema en acceder a los datos, sin embargo, hay ocasiones en las que necesitamos tener más de una fuente de datos [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/12/10/data-access-object-dao-pattern/">Data Access Object (DAO) Pattern</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter size-large wp-image-2485" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/DAO-pattern-1024x574.jpg" alt="Data Access Object (DAO) Pattern" width="648" height="363" />Prácticamente todas las aplicaciones de hoy en día, requiere acceso al menos a una fuente de datos, dichas fuentes son por lo general base de datos relacionales, por lo que muchas veces no tenemos problema en acceder a los datos, sin embargo, hay ocasiones en las que necesitamos tener más de una fuente de datos o la fuente de datos que tenemos puede variar, lo que nos obligaría a refactorizar gran parte del código. Para esto, tenemos el patrón Arquitectónico Data Access Object (DAO), el cual permite separar la lógica de acceso a datos de los Bussines Objects u Objetos de negocios, de tal forma que el DAO encapsula toda la lógica de acceso de datos al resto de la aplicación.<span id="more-2484"></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Problemática</h2>
<p>Una de las grandes problemáticas al momento de acceder a los datos, es que <strong>la implementación y formato de la información puede variar según la fuente de los datos</strong>. Implementar la lógica de acceso a datos en la capa de lógica de negocio puedes ser un gran problema, pues tendríamos que lidiar con la lógica de negocio en sí, más la implementación para acceder a los datos, adicional, si tenemos múltiples fuentes de datos o estas pueden variar, tendríamos que implementar las diferentes lógicas para acceder las diferentes fuentes de datos, como podrían ser: bases de datos relacionales, No SQL, XML, archivos planos, Webservices, etc).</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Solución</h2>
<p>Dado lo anterior, <strong>el patrón DAO propone separar por completo la lógica de negocio de la lógica para acceder a los datos</strong>, de esta forma, el DAO proporcionará los métodos necesarios para insertar, actualizar, borrar y consultar la información; por otra parte, la capa de negocio solo se preocupa por lógica de negocio y utiliza el DAO para interactuar con la fuente de datos.</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2486" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/UML-clases-1024x493.png" alt="Data Access Object (DAO) pattern - Diagrama de clases" width="648" height="312" /></p>
<p>&nbsp;</p>
<p>Los compones que conforman el patrón son:</p>
<ul>
<li><strong>BusinessObject</strong>: representa un objeto con la lógica de negocio.</li>
<li><strong>DataAccessObject</strong>: representa una capa de acceso a datos que oculta la fuente y los detalles técnicos para recuperar los datos.</li>
<li><strong>TransferObject</strong>: este es un objeto plano que implementa el patrón <a href="https://www.oscarblancarteblog.com/2018/11/30/data-transfer-object-dto-patron-diseno/">Data Transfer Object (DTO)</a>, el cual sirve para transmitir la información entre el DAO y el Business Service.</li>
<li><strong>DataSource</strong>: representa de forma abstracta la fuente de datos, la cual puede ser una base de datos, Webservices, LDAP, archivos de texto, etc.</li>
</ul>
<p>&nbsp;</p>
<p>El siguiente diagrama muestra mejor la forma en que funciona el patrón, pues muestra de forma secuencial la forma en que se ejecutaría el patrón.</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2487" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/UML-sequence-1024x633.png" alt="Data Access Object (DAO) pattern - Diagrama de secuencia" width="648" height="401" /></p>
<p>&nbsp;</p>
<p>El diagrama se interpreta de la siguiente manera:</p>
<ol>
<li>El <em>BusinessObject</em> creo u obtiene una referencia al <em>DataAccessObject</em>.</li>
<li>El <em>BusinessObject</em> solicita información al <em>DataAccessObject</em>
<ul>
<li>El <em>DataAccessObject</em> solicita la información al <em>DataSource</em></li>
<li>El <em>DataAccessObject</em> crea una instancia del TransferObject con los datos recuperados del <em>DataSource</em></li>
<li>El <em>DataAccessObject</em> response con el <em>TransferObject</em> creado en los pasos anteriores.</li>
</ul>
</li>
<li>El <em>BusinessObject</em> actualiza algún valor del <em>TransferObject</em>
<ul>
<li>Más actualizaciones</li>
</ul>
</li>
<li>El <em>BusinessObject</em> solicita el guardado de los datos actualizados al <em>DataAccessObject</em>.
<ul>
<li>El <em>DataAccessObject</em> guarda los datos en el <em>DataSource</em>.</li>
</ul>
</li>
</ol>
<p>&nbsp;</p>
<p>Como hemos podido ver, el <em>BusinessService</em> no se preocupa de donde vengan los datos ni cómo deben de ser guardados en el <em>DataSource</em>, el solo se preocupa por conocer el <em>TransferObject</em>. Un error común al implementar este patrón es no utilizar <em>TransferObject</em> y en su lugar, regresar los objetos que regresan las mismas API’s de las fuentes de datos, ya que esto obliga al <em>BusinessService</em> tener una dependencia con estas librerías, además, si la fuente de datos cambia, también cambiarán estas clases, lo que provocaría una afectación directa al <em>BusinessService</em>.</p>
<p>&nbsp;</p>
<blockquote><p>Hace unos días escribir sobre el patrón <a href="https://www.oscarblancarteblog.com/2018/11/30/data-transfer-object-dto-patron-diseno/">Data Transfer Object (DTO)</a> por si quieres profundizar en el tema.</p></blockquote>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>DAO y el patrón Abstract Factory</h2>
<p>Hasta este punto solo hemos analizado como trabajaríamos si solo tuviéramos una fuente de datos, sin embargo, existe ocasiones donde requerimos obtener datos de más de una fuente, y es allí donde entra el patrón de diseño <a href="https://reactiveprogramming.io/books/design-patterns/es/catalog/abstract-factory" target="_blank" rel="noopener">Abstract Factory</a> el cual explico perfectamente en mi libro “Introducción a los patrones de diseño”.</p>
<p>&nbsp;</p>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones como este? te invito a que veas mi libro de &#8220;Introducción a los patrones de diseño&#8221;, donde aprenderás los principales patrones de diseño con ejemplos del mundo real, olvídate de aprender con los ejemplos típicos de Internet, como hacer una pizza, crear clase de animales que ladren o figuras geométricas.</figcaption></figure>
<p>&nbsp;</p>
<p>Mediante el patrón Abstract Factory podemos definir una serie de familias de clases que permitan conectarnos a las diferentes fuentes de datos. Para esto, examinaremos un sistema de autenticación de usuarios, el cual puede leer los usuarios en una base de datos o sobre un XML, adicional, el sistema generara registros de login que podrán ser utilizados para auditorias.</p>
<p>Lo primero sería implementar las clases para acceder de las dos fuentes:</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-2488" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/UML-Diagramas-Familys.png" alt="Data Access Object (DAO) pattern - Abstract Factory familias" width="521" height="133" /></p>
<p>&nbsp;</p>
<p>En la imagen anterior podemos apreciar dos familias de clases, con las cuales podemos obtener los Usuarios y los registros de auditoria, sin embargo, estas clases por separado no ayudan mucho, pues no implementan una misma interface que permita la variación entre ellas, por lo que el siguiente paso es crear estas interfaces:</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-2489" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/UML-Diagramas-Familiy-interfce.png" alt="Data Access Object (DAO) pattern - Abstract factory interfaces" width="521" height="301" /></p>
<p>&nbsp;</p>
<p>En este punto, los DAO ya implementan una interfaz común, lo que permite intercambiar la implementación sin afectar al Business Object. Sin embargo, ahora solo falta resolver la forma en que el Business Service obtendrá la familiar de interfaces, es por ello que deberemos crear un Factory para cada familia de interfaces:</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-2490" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/UML-Diagramas-Family-Factory.png" alt="Data Access Object (DAO) pattern - Abstract factory full implementation" width="521" height="546" /></p>
<p>&nbsp;</p>
<p>En esta nueva configuración, podemos ver que tenemos un Factory para cada familia, y los dos factorys implementan una interfaz en común, adicional, tenemos la interface <em>IDAOFactory</em> necesaria para que el factory de cada familia implementen una interface en común.</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2491" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/dao-factory-1024x544.png" alt="Data Access Object (DAO) pattern - Abtract factory sequence" width="648" height="344" /></p>
<p>&nbsp;</p>
<p>Analicemos como quedaría la secuencia de ejecución</p>
<ol>
<li>El <em>BusinessObject</em> solicita la creación de un <em>DAOFactory</em> para SQL
<ul>
<li>El <em>DAOFactory</em> crea una instancia de la clase <em>SQLDAOFactory </em>y la retorna</li>
</ul>
</li>
<li>El <em>BusinessObject</em> solicita al <em>SQLDAOFactory</em> la creación del <em>SQLUserDAO</em> para interactuar con los usuarios.
<ul>
<li>El <em>SQLDAOFactory</em> crea una nueva instancia del <em>SQLUserDAO</em></li>
<li>El <em>SQLDAOFactory</em> retorna la instancia creada del <em>SQLUserDAO</em></li>
</ul>
</li>
<li>El <em>BusinessObject</em> solicita el listado de todos los usuarios registrados al <em>SQLUserDAO</em>
<ul>
<li>El <em>SQLUserDAO</em> recupera los usuarios del <em>SQLDataSource</em></li>
<li>El <em>SQLUserDAO</em> crea un <em>TransferObject</em> con los datos recuperados del paso anterior.</li>
<li>El <em>SQLUserDAO</em> retorna el <em>TransferObject</em> creado en el paso anterior.</li>
</ul>
</li>
</ol>
<p>Adicional a los pasos que hemos listado aquí, podríamos solicitar al <em>SQLDAOFactory</em> la creación del <em>SQLAuditDAO</em> o incluso, solicitar al <em>DAOFactory</em> la creación del <em>XMLFactory</em> para interactuar con la fuente de datos en XML.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Conclusiones</h2>
<p>El patrón DAO es sin lugar a duda, unos de los más utilizados en la actualidad, ya que es fácil de implementar y proporciona claros beneficios, incluso, si solo tenemos una fuente de datos y esta no cambia, pues permite separar por completo la lógica de acceso a datos en una capa separada y así solo nos preocupamos por la lógica de negocio sin preocuparnos de donde viene los datos o los detalles técnicos para consultarlos o actualizarlos.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/12/10/data-access-object-dao-pattern/">Data Access Object (DAO) Pattern</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2018/12/10/data-access-object-dao-pattern/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2484</post-id>	</item>
		<item>
		<title>Patrón de diseño Command</title>
		<link>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/</link>
					<comments>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 19 Nov 2014 10:00:00 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<guid isPermaLink="false">http://javamex.wordpress.com/?p=427</guid>

					<description><![CDATA[<p>El patrón de diseño Command es muy utilizado cuando se requiere hacer ejecuciones de operaciones sin conocer realmente lo que hacen, estas operaciones son conocidas como comandos y son implementadas como una clase independiente que realiza una acción muy concreta, para lo cual,únicamente recibe un conjunto de parámetros para realizar su tarea. La siguiente imagen [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/">Patrón de diseño Command</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter wp-image-1570 " src="https://www.oscarblancarteblog.com/wp-content/uploads/2014/11/Command-pattern.jpg" alt="Patrón de diseño Command" width="859" height="482" />El patrón de diseño <strong>Command</strong> es muy utilizado cuando se requiere hacer ejecuciones de operaciones sin conocer realmente lo que hacen, estas operaciones son conocidas como comandos y son implementadas como una clase independiente que realiza una acción muy concreta, para lo cual,únicamente recibe un conjunto de parámetros para realizar su tarea.<span id="more-427"></span></p>
<p style="text-align: justify;">La siguiente imagen muestra la estructura del patrón de diseño:</p>
<figure style="width: 581px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise1.png" alt="Patrón de diseño Command" width="581" height="453" /><figcaption class="wp-caption-text">Fig.1: En la imagen podemos apreciar cómo está diseñado el patrón de diseño Command.</figcaption></figure>
<p>&nbsp;</p>
<p>En la imagen podemos apreciar los siguientes elementos:</p>
<p><strong>ICommand: </strong>Esta es la pieza más importante del patrón, ya que cada comando deberá implementar esta interface y deberá implementar el método <strong>execute</strong>, el cual, de forma <a title="Que es el Polimorfismo?" href="http://oscarblancarteblog.com/2014/07/15/que-es-el-polimorfismo/">polimórfica </a>realizara la operación que deseamos. Este componente generalmente es una interface o una clase abstract.</p>
<p><strong>Concrete Command: </strong>Para este componente hablaremos en plural, ya que cada Concrete Command que tengamos implementado se convertirá en un comando en nuestro patrón. Este componente tiene que implementar <strong>ICommand </strong>de forma directa o indirecta y deberá implementar el método <strong>execute</strong>, en el cual se realizara la operación que deseamos que realice el comando.</p>
<p><strong>Command Manager: </strong>Este componente nos servirá para administrar los comandos que tenemos disponibles en tiempo de ejecución, desde aquí podemos ejecutar un Comando o registrar nuevos comandos para que estén disponibles en tiempo de ejecución. Esta clase es importante, ya que de nada sirve tener un conjunto de <strong>Concrete Command</strong> que implementan <strong>ICommand</strong> regados por nuestro proyecto si no tenemos un componente que los administre y nos permite ejecutarlos.</p>
<p><strong>Invoker: </strong>El invoker representa a la acción que dispara alguno de los comandos, un invoker podría ser un usuario, una aplicación o algún evento generado por nuestra aplicación.</p>
<p>Ya que conocemos los componentes es hora de hablar un poco más del Patrón de diseño, Al comienzo comentamos que nos sirve para realizar operaciones sin conocer realmente que hace la operación. Para lo cual utilizaremos un ejemplo y veremos de qué forma este patrón lo resuelve.</p>
<p>A estas alturas me imagino que todos ya hemos utilizado alguna vez la consola de Windows o Unix. Si observamos la consola, veremos que ella response a base de comandos, estos comandos pueden o no necesitar parámetros para funcionar, lo asombroso aquí es que la consola tiene la característica de saber siempre que operación va a realizar sin tener que decirle que clase o que software utilice para realizar la tarea, ya que la consola es capaz de determinar el comando utilizado y ejecutar el componente o software que realizar la operación deseada.</p>
<p>Otro punto importante es que la consola tiene la característica de agregarle comandos a medida que instalamos nuevo software como es el caso de Java, si intentamos ejecutar el comando <strong><em>java –version</em></strong>, con una computadora la cual no tiene instalado Java veras que te arrojara un mensaje de comando no encontrado, sin embargo si tu ejecutas de nuevo el comando una vez instalado java, entonces obtener un mensaje como el siguiente <strong><em>java version &#8220;1.7.0_51&#8243;…..</em></strong>, En el patrón Command podemos registrar nuevos comandos mediante el componente CommandManager lo cual lo veremos más a delante.</p>
<p>Para analizar mejor este Patrón de diseño analizaremos el ejemplo de la consola y desarrollaremos una mediante el <strong>Patrón Command</strong>. Para iniciar el ejemplo tendremos que pensar primero en la funcionalidad que le daremos a nuestra consola, en este ejemplo desarrollaremos comandos muy simples pero útiles que ayuden a demostrar la utilidad del patrón, para lo cual les dejo la siguiente imagen:</p>
<figure style="width: 572px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise2.png" alt="Patrón de diseño Command" width="572" height="447" /><figcaption class="wp-caption-text">Fig.2: La siguiente imagen muestra los comandos que desarrollaremos en el ejemplo.</figcaption></figure>
<p>Podemos identificar a los comandos de forma muy simple ya que son todos aquellos que implementan <strong>ICommand</strong> de forma directa o indirecta, cada comandos tiene un nombre diferente el cual lo utilizaremos para ejecutarlos desde nuestra consola. La explicación de los comandos está a continuación.</p>
<p><strong>Exit: </strong>finaliza la consola y termina con nuestro programa.</p>
<p><strong>Memory: </strong>Nos muestra en pantalla la cantidad de memoria total disponible, utilizada y máxima que podemos utilizar.</p>
<p><strong>Batch: </strong>Comando que ejecuta en lote un conjunto de comandos definidos en un archivo plano.</p>
<p><strong>Echo: </strong>Comando que nos imprime en pantalla lo que escribimos en la consola.</p>
<p><strong>Date: </strong>Comando que nos imprime en pantalla la hora y la fecha en el formato que queramos.</p>
<p><strong>File: </strong>Comando que nos permite interactuar con archivos, como crear, borrar, escribir, etc.</p>
<p><strong>Dir: </strong>Nos permite realizar operaciones con directorios, ya sea crearlos o borrarlos.</p>
<p><strong>WaitHello:</strong> Comando que nos permite demostrar la ejecución en segundo plano, este comando al ejecutarse escribe &#8220;Hello!&#8221; Después de un tiempo determinado.</p>
<p>A demás de los comandos tenemos los Abstract Command, los cuales están representados en el diagrama de color azul, estos comandos no hacen una funcionalidad como tal, sin embargo ayudan a crear otros comandos más complejos, los <strong>Abstract Command</strong> que tenemos aquí hace lo siguiente:</p>
<p><strong>BaseCommand: </strong>Comando que agrega únicamente el método <strong>write</strong> el cual nos ayuda a escribir en pantalla los eventos generados por nuestros comandos, además de que nos permite tener un método estándar de escritura que podría ser modificado para afectar a todos los comandos, ahorrándonos el problema de modificar cada comando para que escriba de forma distinta.</p>
<p><strong>AsyncCommand: </strong>Este comando tiene como finalidad demostrar que también se pueden crear comandos que se ejecuten en segundo plano, este comando tiene la característica que ejecuta la acción en un hilo independiente por lo que podemos seguir trabajando con la consola sin que el comando haya terminado de ejecutarse. Otro punto importante es que implementa el método <strong>execute</strong>, pero agrega el método abstracto <strong><em>executeOnBackground</em></strong>, en el cual deberemos implementar la función que queremos que realice en segundo plano.</p>
<figure style="width: 627px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise3.png" alt="Patrón de diseño Command" width="627" height="404" /><figcaption class="wp-caption-text">Fig.3: La imagen muestra un diagrama de secuencia de cómo se lleva a cabo la ejecución de un comando.</figcaption></figure>
<p>&nbsp;</p>
<h2><span style="font-size: 12pt;"><strong>Implementación:</strong></span></h2>
<p>Una vez platicado el escenario podemos pasar a la implementación de la consola.</p>
<p><strong>Clase ICommand:</strong> Interface que tiene como propósito definir la estructura mínima de un comando, Esta interface define dos métodos, <strong><em>getCommandName</em></strong> el cual regresa el nombre del comando para uso informativo, También tiene el método <strong><em>execute</em></strong> el cual es implementado por los comandos para realizar la operación deseada, el método recibe un arreglo de String que corresponde a los parámetros del comando y un OutputStream el cual utilizaremos para ir notificando al usuario todas las cosas relevantes como un mensaje o un error.</p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Interface ICommand ">package javamex.patronesdiseño.command;

import java.io.OutputStream;

public interface ICommand {

    public String getCommandName();

    public void execute(String[] args, OutputStream out);
}</pre>
<p>&nbsp;</p>
<p>Clase CommanManager: Esta clase es utilizada para gestionar los comandos disponibles en nuestra aplicación, desde esta clase podremos registrar nuevos comandos y recuperar los comandos solicitados por el usuario, La clase contiene los siguientes métodos:</p>
<ul>
<li>getCommand: Este método recibe como parámetro un String el cual corresponde al nombre del comando solicitado, El comando es buscado y retornado, pero si un comando no es encontrado se regresa un comando de error el cual explicaremos más a delante.</li>
<li>registCommand: Método utilizado para registrar los commandos que tendremos disponibles en tiempo de ejecución, para que un comando esté disponible en la aplicación primero tendrá que ser registrado.</li>
<li>getIntance: Método que nos permite obtener una instancia de la clase CommanManager ya que la esta clase sigue el patrón de diseño Singleton(Hablare de el en otra entrada).</li>
</ul>
<p>Un punto importante a resaltar el constructor de la clase, en el cual registramos todos los comandos disponibles de forma predefinida para que estén disponibles en tiempo de ejecución, por defecto, cualquier comandos que creemos y que no se encuentre registrados no podrá ser reconocido.<span style="font-size: 10pt;"><br />
</span></p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase CommandManager">package javamex.patronesdiseño.command;

import java.util.HashMap;
import javamex.patronesdiseño.command.impl.*;

public class CommandManager {

    private static CommandManager commandManager;

    private static final HashMap&lt;String, Class&lt;? extends ICommand&gt;&gt; COMMANDS =
            new HashMap&lt;String, Class&lt;? extends ICommand&gt;&gt;();

    private CommandManager() {
        registCommand(EchoCommand.COMMAN_NAME, EchoCommand.class);
        registCommand(DirCommand.COMMAND_NAME, DirCommand.class);
        registCommand(DateTimeCommand.COMMAND_NAME, DateTimeCommand.class);
        registCommand(MemoryCommand.COMMAN_NAME, MemoryCommand.class);
        registCommand(FileCommand.COMMAND_NAME, FileCommand.class);
        registCommand(ExitCommand.COMMAND_NAME, ExitCommand.class);
        registCommand(BatchCommand.COMMAND_NAME, BatchCommand.class);
        registCommand(WaitAndSayHello.COMMAND_NAME, WaitAndSayHello.class);
    }

    public static synchronized CommandManager getIntance() {
        if (commandManager == null) {
            commandManager = new CommandManager();
        }
        return commandManager;
    }

    public ICommand getCommand(String commandName) {
        if (COMMANDS.containsKey(commandName.toUpperCase())) {
            try {
                return COMMANDS.get(commandName.toUpperCase()).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return new ErrorCommand();
            }
        } else {
            return new NotFoundCommand();
        }
    }

    public void registCommand(String commandName, 
            Class&lt;? extends ICommand&gt; command) {
        COMMANDS.put(commandName.toUpperCase(), command);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Commandos: </strong>Las siguientes clases representan las implementaciones de los comandos que tendremos disponibles en la aplicación, los cuales fueron registrados en el constructor de CommandManager. Las clases siguientes representan los comandos que analizamos en la figura 2.</p>
<p><strong>Clase ExitCommand: </strong>Comandos que termina con la aplicación. Este comando implementa <em><strong>ICommand</strong> </em>por lo que representa unos de los comandos más simples de la aplicación.<strong><br />
</strong></p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase ExitCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import javamex.patronesdiseño.command.ICommand;

public class ExitCommand implements ICommand {

    public static final String COMMAND_NAME = "exit";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        System.exit(0);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase BaseCommand: </strong>Esta clase implementa ICommand, sin embargo no es como tal un comando ya que es una <strong><em>Clase Abstracta</em></strong>, Esta clase fue diseñado como ejemplo para servir como una base para los demás comandos que imprimen un mensaje en pantalla, esta clase únicamente agrega el método <strong><em>write, </em></strong>El cual es utilizados para que todos los comandos impriman en pantalla los mensajes de una forma controlada, ya que si decidimos cambiar la forma que se escribe solo tendremos que cambiar este método y todas las clases que la heredan serán afectadas.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase BaseCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import javamex.patronesdiseño.command.ICommand;

public abstract class BaseCommand implements ICommand {

    @Override
    public abstract String getCommandName();

    @Override
    public abstract void execute(String[] args, OutputStream out);

    public void write(OutputStream out, String message) {
        try {
            out.write(message.getBytes());
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}</pre>
<p>&nbsp;</p>
<p style="text-align: justify;"><strong>Clase DirCommand: </strong>Comando que nos permite crear o borrar una carpeta de nuestro FileSytem, el comando recibe como parámetro la operación a realizar (crear o borrar {-N|-D}) más la ruta de la carpeta.</p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase DirCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;

import java.io.OutputStream;

import java.nio.channels.WritableByteChannel;

public class DirCommand extends BaseCommand {

    public static final String COMMAND_NAME = "dir";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 2) {
            write(out, COMMAND_NAME + " argumentos insuficientes");
        }
        String operation = args[0];
        if ("-D".equals(operation.toUpperCase())) {
            write(out, deleteDir(args[1]));
        } else if ("-N".equals(operation.toUpperCase())) {
            write(out, newDir(args[1]));
        } else {
            write(out, "Se esperaba una operación correcta -d | -n");
        }
    }

    private String deleteDir(String url) {
        try {
            File file = new File(url);
            if (!file.exists()) {
                return "El archivo no existe";
            }
            if (!file.canWrite()) {
                return "Privilegios insuficientes";
            }
            file.delete();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String newDir(String url) {
        try {
            File file = new File(url);
            if (file.exists()) {
                return "El archivo ya existe";
            }
            file.mkdirs();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }
}</pre>
<p>&nbsp;</p>
<p><strong>FileCommand: </strong>Comando que nos permitirá realizar operaciones con archivos, las operaciones son las siguientes:</p>
<ul>
<li><strong>WRITE_APPEND = -WA:</strong> Permite escribir en un archivo conservando el contenido existente previamente. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir<strong><br />
</strong></li>
<li><strong>WRITE_OVERRIDE = -WO: </strong>Permite escribir en un archive sobrescribiendo su contenido. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir.<strong><br />
</strong></li>
<li><strong>WRITE_NEW = -WN: </strong>Permite crear un archive y luego escribir en él. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir. <strong><br />
</strong></li>
<li><strong>RENAME_FILE = -R: </strong>Permite renombrar un archive existente. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo corresponde al nuevo nombre.<strong><br />
</strong></li>
<li><strong>DELETE_FILE = -D: </strong>Permite borrar un archive. Recibe únicamente el path del archivo a eliminar.<strong><br />
</strong></li>
</ul>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase FileCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.util.Arrays;

public class FileCommand extends BaseCommand {

    public static final String COMMAND_NAME = "file";
    private static final String WRITE_APPEND = "-WA";
    private static final String WRITE_OVERRIDE = "-WO";
    private static final String WRITE_NEW = "-WN";
    private static final String RENAME_FILE = "-R";
    private static final String DELETE_FILE = "-D";

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args.length &lt; 2) {
            write(out, "Parametros insuficientes");
            return;
        }
        String operation = args[0].toUpperCase();
        String[] reduce = Arrays.copyOfRange(args, 1, args.length);
        if (WRITE_APPEND.equals(operation)) {
            write(out, writeAppend(reduce));
        } else if (WRITE_NEW.equals(operation)) {
            write(out, writeNew(reduce));
        } else if (WRITE_OVERRIDE.equals(operation)) {
            write(out, writeOverride(reduce));
        } else if (RENAME_FILE.equals(operation)) {
            write(out, renameFile(reduce));
        } else if (DELETE_FILE.equals(operation)) {
            write(out, deleteFile(reduce));
        } else {
            write(out, "No se encontro la operacion {" + WRITE_APPEND + "|" + WRITE_NEW + "|" + WRITE_OVERRIDE + "|" + RENAME_FILE + "|DELETE_FILE}");
        }
    }

    private String renameFile(String[] args) {
        String filePath = args[0];
        String newFileName = args[1];
        try {
            File file = new File(filePath);
            file.renameTo(new File(newFileName));
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeOverride(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                if (!file.createNewFile()) {
                    return "ERROR: Error al crear el archivo";
                }
            }
            FileWriter fileW = new FileWriter(file);
            fileW.write(fileContent.toCharArray());
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeAppend(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                return "ERRRO: El archivo no existe";
            }
            FileWriter fileW = new FileWriter(file, true);
            fileW.append(fileContent);
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeNew(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (file.exists()) {
                return "ERRRO: El archivo ya existe";
            }
            if (!file.createNewFile()) {
                return "ERROR: No fué posible crear el archivo";
            }
            FileWriter fileW = new FileWriter(file);
            fileW.write(fileContent.toCharArray());
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String deleteFile(String[] args) {
        String filePath = args[0];
        File file = new File(filePath);
        if (!file.delete()) {
            return "No fué posible eliminar el archivo";
        }
        return "";
    }

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>EchoCommand: </strong>Comando que únicamente imprime en pantalla lo que se escribe. Como un Eco.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase EchoCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import java.util.Arrays;

public class EchoCommand extends BaseCommand {

    public static final String COMMAN_NAME = "echo";

    @Override
    public void execute(String[] args, OutputStream out) {
        String message = getCommandName() + " " + Arrays.toString(args);
        write(out, message);
    }

    @Override
    public String getCommandName() {
        return COMMAN_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>DateCommand: </strong>Comando que nos permite conocer la fecha y hora del sistema en el formato que deseemos. El comando únicamente recibe como entrada el formato en el que queremos ver la fecha y hora.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase DateTimeCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTimeCommand extends BaseCommand {

    public static final String COMMAND_NAME = "date";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        SimpleDateFormat dateFormater = null;
        if (args == null) {
            dateFormater = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
        } else {
            try {
                dateFormater = new SimpleDateFormat(args[0]);
            } catch (Exception e) {
                write(out, "formato invalido");
                return;
            }
        }
        String date = dateFormater.format(new Date());
        write(out, date);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>MemoryCommand: </strong>Comando sin parámetros que nos arroja la información de la memoria que utiliza nuestra aplicación.</p>
<pre class="lang:java decode:true" title="Clase MemoryCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class MemoryCommand extends BaseCommand {

    public static final String COMMAN_NAME = "memory";

    @Override
    public String getCommandName() {
        return COMMAN_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        double heap = Runtime.getRuntime().totalMemory() / 1000000d;
        double heapMax = Runtime.getRuntime().maxMemory() / 1000000d;
        double heapFree = Runtime.getRuntime().freeMemory() / 1000000d;
        String salida = "Heap: " + heap + "nMax Heap: " 
                + heapMax + "nFree Heap: " + heapFree;
        write(out, salida);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>BatchCommand: </strong>Commando complejo que nos permite abrir un archivo de comandos, este archivo es parecido a los archivos en batch ya que podemos escribir un conjunto de comandos que serán ejecutados en el orden en el que se encuentran en el archivo(Se asume que cada línea es un comando). El comando únicamente recibe como parámetro el Path del archivo a ejecutar.</p>
<pre class="lang:java decode:true" title="Clase BatchCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Arrays;
import javamex.patronesdiseño.command.CommandManager;
import javamex.patronesdiseño.command.CommandUtil;
import javamex.patronesdiseño.command.ICommand;

public class BatchCommand extends BaseCommand {

    public static final String COMMAND_NAME = "batch";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 1) {
            write(out, "Número de parametros invalido");
            return;
        }
        CommandManager manager = CommandManager.getIntance();
        String[] lines = readLinesFromFile(args[0]);
        for (String line : lines) {
            String[] argsCommand = CommandUtil.tokenizerArgs(line);
            ICommand command = manager.getCommand(argsCommand[0]);
            String[] reduce = Arrays.copyOfRange(argsCommand, 1, argsCommand.length);
            command.execute(reduce, out);
            write(out, "n");
        }
        write(out, "Batch executado");
    }

    private String[] readLinesFromFile(String filePath) throws RuntimeException {
        File file = new File(filePath);
        FileInputStream stream = null;
        try {
            if (!file.exists()) {
                throw new RuntimeException("Archivo no encotrado");
            }
            stream = new FileInputStream(file);
            byte[] byteArray = new byte[stream.available()];
            stream.read(byteArray);
            String commands = new String(byteArray);
            String[] lines = commands.split("n");
            return lines;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                stream.close();
            } catch (Exception e2) {}
        }
    }
}</pre>
<p>&nbsp;</p>
<p><strong>AsyncCommand: </strong>Esta clase al igual que <strong><em>BaseCommand</em></strong> no es como tal un comando ya que es una <strong><em>Clase Abstract</em></strong>, esta clase tiene como propósito demostrar que podemos implementar comandos que se ejecuten en segundo plano o de forma asíncrona.</p>
<p>Esta clase agrega el método <strong><em>executeOnBackground</em></strong> en el cual deberemos implementar la funcionalidad que deseamos que realice el comando. Ya que el método original <strong><em>execute</em></strong> es sobre escritor para ejecutar el método <strong><em>executeOnBackground</em></strong> en un hilo independiente.</p>
<pre class="lang:java decode:true " title="Clase AsyncCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public abstract class AsyncCommand extends BaseCommand {

    public void execute(final String[] args, final OutputStream out) {
        new Thread(new Runnable() {
            public void run() {
                executeOnBackground(args, out);
            }
        }).start();
    }

    public abstract void executeOnBackground(String[] args, OutputStream out);
}</pre>
<p>&nbsp;</p>
<p>Clase WaitAndSeyHello: Comando que extiende de AsyncCommand, lo cual lo convierte automáticamente en un comando que se ejecuta en segundo plano. Ha este comando únicamente se le envía un tiempo en milisegundos, el cual lo utilizara para esperar este tiempo antes de decir Hello! .</p>
<pre class="lang:java decode:true " title="clase WaitAndSayHello">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class WaitAndSayHello extends AsyncCommand {

    public static final String COMMAND_NAME = "waithello";

    @Override
    public void executeOnBackground(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 1) {
            write(out, "Parametros insuficientes");
            return;
        }
        Long time = null;
        try {
            time = Long.parseLong(args[0]);
        } catch (Exception e) {
            write(out, "Tiempo inválido");
            return;
        }

        try {
            Thread.sleep(time.longValue());
            write(out, "Hello!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase ErrorCommand:</strong> Este comando no esté definido en nuestro diagrama y es utilizado por el CommandManager únicamente para regresar un Error al intentar instanciar un comando. Este comando no puede ser ejecutado por el cliente ya que no es un comando registrado, sin embargo CommandManager lo maneja como un comando propio del sistema para representa un error.</p>
<pre class="lang:java decode:true " title="Clase ErrorCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

import java.nio.channels.WritableByteChannel;

public class ErrorCommand extends BaseCommand {

    private static final String COMMAND_NAME = "ERROR";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        String message = "Error al invokar el comando";
        write(out, message);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase NotFoundCommand: </strong>Comando parecido a ErrorCommand pero este es regresado cuando un comando no es encontrado.</p>
<pre class="lang:java decode:true " title="Clase NotFoundCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class NotFoundCommand extends BaseCommand {

    private static final String COMMAND_NAME = "NOT FOUND";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        write(out, "Commando no encontrado");
    }
}</pre>
<p>&nbsp;</p>
<p>Otra clase que se utiliza es <strong><em>CommandUtil, </em></strong>la cual la utilizamos únicamente para procesar los datos tecleados por el usuario y dividir las instrucciones en tokens, los tokes pueden ser el nombre del comando y los parámetros. La regla que se sigue para dividir los comandos es la siguiente.</p>
<p>Cada palabra separada por un espacio es considera como un token a excepción que se encuentre en medio de comillas dobles, ejemplo &#8220;Hola Mundo&#8221;, en este caso toda la oración es considera un único token.</p>
<pre class="lang:java decode:true " title="Clase CommandUtil">package javamex.patronesdiseño.command;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

public class CommandUtil {

    public static String[] tokenizerArgs(String args) {
        List&lt;String&gt; tokens = new ArrayList&lt;String&gt;();
        char[] charArray = args.toCharArray();
        String contact = "";
        boolean inText = false;
        for (char c : charArray) {
            if (c == ' ' &amp;&amp; !inText) {
                if (contact.length() != 0) {
                    tokens.add(contact);
                    contact = "";
                }
            } else if (c == '"') {
                if (inText) {
                    tokens.add(contact);
                    contact = "";
                    inText = false;
                } else {
                    inText = true;
                }
            } else {
                contact += c;
            }
        }
        if (contact.trim().length() != 0) {
            tokens.add(contact.trim());
        }
        String[] argsArray = new String[tokens.size()];
        argsArray = tokens.toArray(argsArray);
        return argsArray;

    }
}</pre>
<p>&nbsp;</p>
<p>Hasta este momento ya tenemos definidos el CommandaManager y todos los comandos que utilizaremos, sin embargo no tenemos un mecanismo que nos ayude interactuar con los comandos, para eso tenemos la clase <strong><em>CommandMain</em></strong>, la cual servirá de invoker, Esta clase se cicla para solicitar al usuario comandos desde la consola.</p>
<pre class="lang:java decode:true " title="Clase CommandMain">package javamex.patronesdiseño.command;

import java.util.Arrays;
import java.util.Scanner;

public class CommandMain {

    public static void main(String[] args) {
        System.out.println("Command Line is Start");
        CommandManager manager = CommandManager.getIntance();
        Scanner in = new Scanner(System.in);
        while (true) {
            String line = in.nextLine();
            if ("EXIT".equals(line.toUpperCase())) {
                System.exit(0);
            }
            if (line.trim().length() == 0) {
                continue;
            }
            String[] commands = CommandUtil.tokenizerArgs(line);
            String commandName = commands[0];
            String[] commandArgs = null;
            if (commands.length &gt; 1) {
                commandArgs = Arrays.copyOfRange(commands, 1, commands.length);
            }
            ICommand command = manager.getCommand(commandName);
            command.execute(commandArgs, System.out);
            System.out.println("");
        }
    }
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="Introducción a los patrones de diseño" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones de diseño como este? te invito a que veas mi libro.</figcaption></figure>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><span style="font-size: 14pt;"><strong>Ejecución:<br />
</strong></span></h2>
<p>Finalmente, ya tenemos listo todo, por lo que comenzaremos ejecutando la aplicación y tendremos como resultado lo siguiente:</p>
<figure style="width: 703px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise4.png" alt="Patrón de diseño Command" width="703" height="279" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Iniciaremos ejecutando el comando <strong><em>date </em></strong>y le pediremos que nos arroje la fecha en el formato &#8220;DD/MM/YYYY&#8221;, seguido le pediremos la hora en el formato &#8220;HH:MM:SS&#8221; y finalmente le pediremos fecha y hora el formato &#8220;DDMMYYYY HHMMSS&#8221; para lo cual utilizaremos la nomenclatura estándar de java para la fecha y hora la cual podremos apreciar en la siguiente pagina <a href="https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html</a>.</p>
<figure style="width: 703px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise5.png" alt="Patrón de diseño Command" width="703" height="238" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Para el siguiente ejemplo, utilizaremos el comando <strong><em>Dir </em></strong>para crear un nuevo directorio y luego lo borraremos.</p>
<figure style="width: 710px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise6.png" alt="Patrón de diseño Command" width="710" height="270" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>&nbsp;</p>
<figure style="width: 722px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise7.png" alt="Patrón de diseño Command" width="722" height="308" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Para el siguiente ejemplo utilizaremos el comando <strong><em>echo</em></strong> para decir &#8220;Hola Mundo&#8221;.</p>
<figure style="width: 678px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise8.png" alt="Patrón de diseño Command" width="678" height="327" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Para el siguiente ejemplo utilizaremos el comando <strong><em>File</em></strong> para crear un nuevo archivo de texto y escribir en el <strong>&#8220;Hola Mundo&#8221; </strong></p>
<figure style="width: 715px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise9.png" alt="Patrón de diseño Command" width="715" height="261" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>El siguiente comando a utilizar es <strong><em>Memory, </em></strong>El cual nos dará datos acerca de la memoria de la aplicación.</p>
<figure style="width: 607px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise10.png" alt="Patrón de diseño Command" width="607" height="340" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Utilizaremos nuevamente el comando <strong><em>File </em></strong>para renombrar el archivo dummy.txt a helloword.txt</p>
<figure style="width: 739px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise11.png" alt="Patrón de diseño Command" width="739" height="231" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Hasta aquí, solamente hemos ejecutado comandos síncronos, pero en este ejemplo ejecutaremos el comando WaitAndSeyHello, el cual lo ejecutaremos y le diremos que espere 10 segundos antes de decir Hello!.</p>
<figure style="width: 633px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise12.png" alt="Patrón de diseño Command" width="633" height="283" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p style="text-align: center;">Después de esperar 10 segundos tenemos el siguiente resultado.</p>
<figure style="width: 640px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise13.png" alt="Patrón de diseño Command" width="640" height="290" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>En el siguiente ejemplo ejecutaremos el comando <strong><em>Batch </em></strong>el cual lee un archivo de texto y ejecuta todos los comandos que tenemos en el, para este ejemplo ejecutaremos el comando y le diremos que lea un archivo en la ruta c:/dummy/batch.txt el cual tendrá el siguiente contenido:</p>
<pre class="lang:sh decode:true ">date dd/MM/yyyy hh:mm:ss
dir -n "c:/dummy/dummy2"
echo "Se creo el archivo dummy2"
file -wn "c:/dummy/dummy2/dummy.txt" "Hola mundo con el comando file"
memory
file -r "c:/dummy/dummy2/dummy.txt" "c:/dummy/dummy2/dummy2.txt"
date dd/MM/yyyy hh:mm:ss</pre>
<p>&nbsp;</p>
<p>Lo que esperemos que realice el comando es lo siguiente: imprime la fecha y hora, cree el directorio c:/dummy/dummy2, escriba en pantalla Se creó el archivo dummy2&#8243;, cree un archivo en &#8220;c:/dummy/dummy2/dummy.txt&#8221; con el contenido &#8220;Hola mundo con el comando file&#8221;, imprima en pantalla los datos de la memoria, renombre el archivo que acabamos de crear y le ponga de nombre dummy2.txt y finalmente imprima nuevamente la fecha y hora.</p>
<figure style="width: 661px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise14.png" alt="Patrón de diseño Command" width="661" height="219" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p style="text-align: center;"><strong> </strong></p>
<p>Otra cosa que podemos intentar es ejecutar un comando que no existe, por ejemplo &#8220;java&#8221;, el cual nos indicara que no fue encontrado.</p>
<figure style="width: 665px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise15.png" alt="Patrón de diseño Command" width="665" height="298" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Finalmente ejecutamos el comando <strong><em>Exit</em></strong>, el cual terminara con la aplicación.</p>
<figure style="width: 670px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise16.png" alt="Patrón de diseño Command" width="670" height="301" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure>
<p>Hasta este punto ya habremos creado una consola que es capaz de ejecutar comandos, los cuales serán ejecutados sin saber realmente que clase está realizando el trabajo, sin embargo en la vida real no nos interés saber cómo es atendido un comando siempre y cuando realice la tarea que esperamos que realice. Y como ya vimos con el patrón de diseño Command esto es posible.</p>
<p>Ya con esta base tú podrás crear nuevos comandos y registrarlos al CommandManager para que los puedes utilizar en tu consola, también podrías crear un comando que se encargue de registrar nuevos comandos desde algún Jar para que esté disponible desde la consola. O podrías modificar la forma en la carga los comandos al inicio para que lea algún archivo de configuración.</p>
<p>Acabamos de ver uno de los muchos aplicativos que tiene el Patrón de diseño Command, Si tú tienes alguna experiencia con este patrón por favor coméntala.</p>
<p>&nbsp;</p>
<p>Ya está a la venta mi nuevo libro &#8220;<a href="http://www.oscarblancarteblog.com/libros/introduccion-los-patrones-diseno/">Introducción a los patrones de diseño</a>&#8220;, en donde expongo los 25 patrones de diseño más utilizados y explicados desde un enfoque del mundo real, con ejemplos que pueden ser aplicados en tus proyectos. Sin duda es unos de los libros más completos de patrones de diseño en español.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/">Patrón de diseño Command</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">427</post-id>	</item>
		<item>
		<title>Patrón de diseño &#8211; Composite</title>
		<link>https://www.oscarblancarteblog.com/2014/10/07/patron-de-diseno-composite/</link>
					<comments>https://www.oscarblancarteblog.com/2014/10/07/patron-de-diseno-composite/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Tue, 07 Oct 2014 18:51:57 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[composite]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<guid isPermaLink="false">http://oscarblancarteblog.com/?p=397</guid>

					<description><![CDATA[<p>El patrón de diseño Composite nos sirve para construir estructuras complejas partiendo de otras estructuras mucho más simples, dicho de otra manera, podemos crear estructuras compuestas las cuales están conformadas por otras estructuras más pequeñas. Para comprender mejor como funciona este patrón imaginemos una casa de ladrillos, las casas como tal no están hecha de [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/10/07/patron-de-diseno-composite/">Patrón de diseño &#8211; Composite</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>El patrón de diseño Composite nos sirve para construir estructuras complejas partiendo de otras estructuras mucho más simples, dicho de otra manera, podemos crear estructuras compuestas las cuales están conformadas por otras estructuras más pequeñas.</p>
<p>Para comprender mejor como funciona este patrón imaginemos una casa de ladrillos, las casas como tal no están hecha de una pieza, si observamos las paredes estas esta echas de pequeñas piezas llamadas ladrillos, entonces, el conjunto de estos ladrillos crea paredes, y un conjunto de paredes crean una casa. este ejemplo puede ser aplicado al patrón Composite, y no digo que vallamos a crear una casa con este patrón, sino más bien nos da una idea de cómo trabaja para poder utilizarlo con otros ejemplos.</p>
<figure id="attachment_398" aria-describedby="caption-attachment-398" style="width: 553px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/composite.png"><img loading="lazy" class="wp-image-398 size-full" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/composite.png" alt="Patrón de diseño Composite" width="553" height="365" /></a><figcaption id="caption-attachment-398" class="wp-caption-text">Fig. 1: Estructura del patrón de diseño Composite.</figcaption></figure>
<p><span id="more-397"></span></p>
<p>El patrón Composite requiere mínimo de tres componentes para poder existir los cuales son Componente, Leaf o Rama y Composite.</p>
<p><strong>Component: </strong>Generalmente es una interface o clase abstracta la cual tiene las operaciones mínimas que serán utilizadas, este componente deberá ser extendido por los otros dos componentes Leaf y Composite. En nuestro ejemplo esto podría representar de forma abstracta un ladrillo o toda la casa (Mas adelante comprenderemos porque)</p>
<p><strong>Leaf:</strong> El leaf u hoja representa la parte más simple o pequeña de toda la estructura y este extiende o hereda de <strong>Component.</strong> En nuestro ejemplo, este representaría un ladrillo de nuestra casa.</p>
<p><strong>Composite: </strong>Aquí es donde está la magia de este patrón, ya que el composite es una estructura conformada por otros Composite y Leaf, si vemos en la imagen 1, vemos que los Composite tiene los métodos <strong>add</strong> y <strong>remove </strong>los cuales nos permiten agregar objetos de tipo <strong>Component</strong>, Sin embargo como hablamos anteriormente, el <strong>Componente</strong> es por lo general un <strong>Interface</strong> o <strong>Clase abstracta </strong> por lo que podremos agregamos objetos de tipo Composite o Leaf. Visto desde el punto de vista del ejemplo de la casa el Composite podría representar un conjunto de ladrillos o la casa completa, Esto desde luego sería agregando varias Ladrillo(Leaf) al Composite para crear una Pared.</p>
<p>No te preocupes si no lograste comprender del todo la explicación anterior, para fortalecer la explicación hablaremos de un ejemplo más técnico donde podamos programar un escenario concreto.</p>
<h2><strong>Caso de estudio del patrón Composite.</strong></h2>
<p>Imaginemos un sistema de punto de venta, en el cual se le pueden vender al cliente una serie de productos, estos productos pueden ser productos <strong>simples (Leaf) </strong>o <strong>paquetes (Composite)</strong>. El sistema permitirá crear Ordenes de ventas las cuales están compuestas por 1 o muchos productos.</p>
<p>La siguiente imagen ilustra la estructura de un paquete.</p>
<figure id="attachment_420" aria-describedby="caption-attachment-420" style="width: 523px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/compositeconceptual1.png"><img loading="lazy" class="wp-image-420 size-full" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/compositeconceptual1.png" alt="Patrón de diseño Composite" width="523" height="376" /></a><figcaption id="caption-attachment-420" class="wp-caption-text">Fig. 2: Imagen que muestra de forma gráfica como esta compuesto un paquete, Los paquete están creados a partir de un conjunto de productos simples y otros paquetes por lo que el precio de un paquete esta calculado por el precio de sus hijos de forma recursiva.</figcaption></figure>
<p>La imagen 2 muestra la estructura de una forma conceptual, sin embargo la estructura es un poco más compleja, ya que está formado por una estructura de dato llamada <a href="http://oscarblancarteblog.com/2014/08/22/estructura-de-datos-arboles/">Árbol</a>.</p>
<figure id="attachment_403" aria-describedby="caption-attachment-403" style="width: 516px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/compositearbol2.png"><img loading="lazy" class="wp-image-403 size-full" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/10/compositearbol2.png" alt="Patrón de diseño Composite" width="516" height="372" /></a><figcaption id="caption-attachment-403" class="wp-caption-text">Fig. 3: La imagen muestra un solo paquete es cual esta formado de otros productos simple y compuestos, un compuesto seria otro paquete, el cual tiene dentro mas productos simples. y como vimos en la figura 2, el precio de un paquete es calculado por el precio de todos los hijos de forma recursiva.</figcaption></figure>
<p>Puntos importantes a tomar en cuenta:</p>
<ul>
<li>Un paquete es producto compuesto de varios productos simples y otros paquetes.</li>
<li>Los paquetes y productos simples deberán ser tratados de la misma forma, por lo que deberán tener un padre en común.</li>
<li>El precio de un paquete es la suma de todos los productos simples que contenga.</li>
<li>El sistema deberá mostrar el total de la Orden y los productos que contiene.</li>
</ul>
<p>Ya conocida la teoría, pasemos a la práctica.</p>
<p><strong>En primero lugar crearemos la clase la cual será nuestro Component</strong></p>
<pre class="lang:java decode:true ">package javamex.patronesdiseño.composite;

/**
 * @author oblancarte
 * 
*/
public abstract class AbstractProduct {

    protected String name;
    protected double price;

    public AbstractProduct(String name, double price) {
        super();
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}</pre>
<p>Como podemos observar la clase AbstractProduct es una clase abstracta la cual define las características mínimas de un producto, las cuales deben tener todos los productos sin importar que sean productos simples o paquetes. Para este ejemplo, lo minino que un producto debe tener es un nombre y un precio.</p>
<p><strong>En segundo lugar, definimos lo que vendría siendo el Leaf o producto simple.</strong></p>
<pre class="lang:java decode:true ">package javamex.patronesdiseño.composite;

public class SimpleProduct extends AbstractProduct {

    protected String brand;

    public SimpleProduct(String name, double price, String brand) {
        super(name, price);
        this.brand = brand;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}</pre>
<p>Lo primero que observamos es que las clases SimpleProduct extiende de AbstractProduct, luego solo como ejemplo agregamos un atributo que solo un producto simple pueda tener, en este caso, agregamos la marca, aunque en este ejemplo no nos sirve de nada nos da una idea de que podemos personalizar los productos según el tipo.</p>
<p>Otro punto importante es que el método getPrice no lo sobre escribimos por lo que toma el heredado de AbstractProduct el cual solo regresa el precio de la propiedad <strong>price</strong>.</p>
<p><strong>Para completar el patrón tenemos el Composite, el cual es una agrupación de AbstractProduct.</strong></p>
<pre class="lang:java decode:true ">package javamex.patronesdiseño.composite;

import java.util.ArrayList;
import java.util.List;

public class CompositeProduct extends AbstractProduct {

    private List&lt; AbstractProduct &gt; products = new ArrayList&lt; AbstractProduct &gt;();

    public CompositeProduct(String name) {
        super(name, 0);
    }

    @Override
    public double getPrice() {
        double price = 0d;
        for (AbstractProduct child : products) {
            price += child.getPrice();
        }
        return price;
    }

    @Override
    public void setPrice(double price) {
        throw new UnsupportedOperationException();
    }

    public void addProduct(AbstractProduct product) {
        this.products.add(product);
    }

    public boolean removeProduct(AbstractProduct product) {
        return this.products.remove(product);
    }
}
</pre>
<p>Lo primero a observar en la clase CompositeProduct es que extiende también la clase AbstractProduct lo cual nos garantiza que tanto el SimpleProduct (Producto Simple) y el CompositeProduct(Paquete) puedan ser tratados de igual manera y nos nos interesa saber en tiempo de ejecución si es un paquete o un producto simple.</p>
<p>En el caso de CompositeProduct veremos que las propiedades que tiene no son las de un producto o paquete, sino que además de tener las que hereda de SimpleProduct, tiene una Lista de AbstractProduct, lo cual nos dice que en esta lista puede tener cualquier objeto que herede de esta clase, y para nuestro ejemplo estas clases serian SimpleProduct y CompositeProduct, Es aquí donde nos damos cuenta que un paquete puede estar compuesto por paquetes y productos simples.</p>
<p>Observemos también el método getPrice y setPrice, el método getPrice es sobre escrito para regresar el precio de todos los productos que contiene y el método setPrice es sobre escrito para que no nos permita establecer un precio, de esta forma cumplimos la regla de que el precio de un paquete es la suma del precio de todos los productos que contiene.</p>
<p>Por último, veamos los métodos addProduct y removeProduct los cuales nos permite agregar y remover productos de un paquete.</p>
<p><strong>Para poder realizar una venta es necesario crear un Orden de venta, por lo que se crear la clase SaleOrder la cual nos permite agregar los productos a vender.</strong></p>
<pre class="lang:java decode:true">package javamex.patronesdiseño.composite;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * @author oblancarte
 * 
*/
public class SaleOrder {

    private long orderId;
    private String customer;
    private Calendar dateTime;
    private List&lt; AbstractProduct &gt; products = new ArrayList&lt; &gt;();

    public SaleOrder(long orderId, String customer) {
        super();
        this.orderId = orderId;
        this.customer = customer;
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
    }

    public String getCustomer() {
        return customer;
    }

    public void setCustomer(String customer) {
        this.customer = customer;
    }

    public Calendar getDateTime() {
        return dateTime;
    }

    public void setDateTime(Calendar dateTime) {
        this.dateTime = dateTime;
    }

    public List getProducts() {
        return products;
    }

    public void setProducts(List products) {
        this.products = products;
    }

    public double getPrice() {
        double price = 0d;
        for (AbstractProduct child : products) {
            price += child.getPrice();
        }
        return price;
    }

    public void addProduct(AbstractProduct product) {
        products.add(product);
    }

    public void removeProduct(AbstractProduct product) {
        products.remove(product);
    }

    public void printOrder() {

        NumberFormat formater = new DecimalFormat("###,##0.00");
        System.out.println("\n=============================================nOrden: " + orderId + "nCliente: " + customer + "nProductos:n");
        for (AbstractProduct prod : products) {
            System.out.println(prod.getName() + "ttt$ " + formater.format(prod.getPrice()));

        }
        System.out.println("Total: " + formater.format(getPrice()) + "n=============================================");
    }
}</pre>
<p>Veamos que la clase SaleOrden no tiene más que una lista de productos, id, fecha de venta y el nombre del cliente (Datos solo como ejemplo).</p>
<p>Como puntos importantes podemos ver los métodos addProduct y removeProduct, los cuales nos permiten agregar y remover productos a la Orden.</p>
<p>Tenemos el método getPrice, el cual nos regresa el precio total de la Orden.</p>
<p>PrintOrden método que imprime el detalle de la Orden en pantalla.</p>
<p><strong>Ejecución.</strong></p>
<p>Para finalizar este ejemplo veremos la clase Main donde veremos cómo funciona el ejemplo:</p>
<pre class="lang:java decode:true ">package javamex.patronesdiseño.composite;

public class Main {

    public static void main(String[] args) {
        SimpleProduct ram4gb = new SimpleProduct("Memoria RAM 4GB", 750, "KingStone");
        SimpleProduct ram8gb = new SimpleProduct("Memoria RAM 8GB", 1000, "KingStone");

        SimpleProduct disk500gb = new SimpleProduct("Disco Duro 500GB", 1500, "ACME");
        SimpleProduct disk1tb = new SimpleProduct("Disco Duro 1TB", 2000, "ACME");

        SimpleProduct cpuAMD = new SimpleProduct("AMD phenon", 4000, "AMD");
        SimpleProduct cpuIntel = new SimpleProduct("Intel i7", 4500, "Intel");

        SimpleProduct smallCabinete = new SimpleProduct("Gabinete Pequeño", 2000, "ExCom");
        SimpleProduct bigCabinete = new SimpleProduct("Gabinete Grande", 2200, "ExCom");

        SimpleProduct monitor20inch = new SimpleProduct("Monitor 20'", 1500, "HP");
        SimpleProduct monitor30inch = new SimpleProduct("Monitor 30'", 2000, "HP");

        SimpleProduct simpleMouse = new SimpleProduct("Raton Simple", 150, "Genius");
        SimpleProduct gammerMouse = new SimpleProduct("Raton Gammer", 750, "Alien");

//Computadora para Gammer que incluye 8gb de ram,disco de 1tb, procesador Intel i7
//gabinete grande,monitor de 30' y un mouse gammer.
        CompositeProduct gammerPC = new CompositeProduct("Gammer PC");
        gammerPC.addProduct(ram8gb);
        gammerPC.addProduct(disk1tb);
        gammerPC.addProduct(cpuIntel);
        gammerPC.addProduct(bigCabinete);
        gammerPC.addProduct(monitor30inch);
        gammerPC.addProduct(gammerMouse);

//Computadora para Casa que incluye 4gb de ram,disco de 500gb, procesador AMD Phenon
//gabinete chico,monitor de 20' y un mouse simple.
        CompositeProduct homePC = new CompositeProduct("Casa PC");
        homePC.addProduct(ram4gb);//
        homePC.addProduct(disk500gb);
        homePC.addProduct(cpuAMD);
        homePC.addProduct(smallCabinete);
        homePC.addProduct(monitor20inch);
        homePC.addProduct(simpleMouse);

//Paque compuesto de dos paquetes, El paquete Gammer PC y Home PC
        CompositeProduct pc2x1 = new CompositeProduct("Paquete PC Gammer + Casa");
        pc2x1.addProduct(gammerPC);
        pc2x1.addProduct(homePC);

        SaleOrder gammerOrder = new SaleOrder(1, "Juan Perez");
        gammerOrder.addProduct(gammerPC);
        gammerOrder.printOrder();

        SaleOrder homeOrder = new SaleOrder(2, "Marcos Guerra");
        homeOrder.addProduct(homePC);
        homeOrder.printOrder();

        SaleOrder comboOrder = new SaleOrder(3, "Paquete 2x1 en PC");
        comboOrder.addProduct(pc2x1);
        comboOrder.printOrder();

        SaleOrder customOrder = new SaleOrder(4, "Oscar Blancarte");
        customOrder.addProduct(homePC);
        customOrder.addProduct(ram8gb);
        customOrder.addProduct(ram4gb);
        customOrder.addProduct(monitor30inch);
        customOrder.addProduct(gammerMouse);
        customOrder.printOrder();
    }
}</pre>
<p><strong>De la linea 5 a la 21 creamos los productos simples.</strong> Los cuales únicamente contiene el nombre del producto y el precio de venta.</p>
<p>Estos productos son instancias de SimpleProduct por lo que vendrían siendo el Leaf del patrón de diseño.</p>
<p><strong>En las lineas 23 a la 47 podemos ver como se crean los paquetes o productos compuestos. </strong>Estos productos solo son creados con el nombre del paquete y no tiene un precio de venta. Una vez creados se les agregan los productos simples mediante el método addProduct, Si vemos bien los paquetes que creamos, veremos que todos están conformados por productos simples a excepción del paquete pc2x1 el cual es un paquete creado a partir de dos paquetes. Esto provocara que el precio de este paquete sea el precio de los dos paquetes hijos, y el precio de los hijos sera el precio de todos los productos simple que contiene, de esta forma creamos un árbol parecido al que vimos en la figura 3.</p>
<p><strong>Por ultimo de la 48 a la 66 se crean 4 ordenes con productos distintos. </strong>En la orden 1 y 2 vemos que solo vendemos un paquete, en la orden 3 vendemos un paquete conformado de dos paquetes y en la orden 4 vendemos un paquete y 4 productos simples.</p>
<p><strong>Resultado de la ejecución:</strong></p>
<p>El resultado de la ejecución del programa nos da el siguiente resultado:</p>
<pre class="">=============================================
Orden: 1
Cliente: Juan Perez
Productos:

Gammer PC $ 12,450.00
<strong>Total: 12,450.00</strong>
=============================================

=============================================
Orden: 2
Cliente: Marcos Guerra
Productos:

Casa PC $ 9,900.00
<strong>Total: 9,900.00</strong>
=============================================

=============================================
Orden: 3
Cliente: Paquete 2x1 en PC
Productos:

Paquete PC Gammer + Casa $ 22,350.00
<strong>Total: 22,350.00</strong>
=============================================

=============================================
Orden: 4
Cliente: Oscar Blancarte
Productos:

Casa PC $ 9,900.00
Memoria RAM 8GB $ 1,000.00
Memoria RAM 4GB $ 750.00
Monitor 30' $ 2,000.00
Raton Gammer $ 750.00
<strong>Total: 14,400.00</strong>
=============================================</pre>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener noreferrer"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="Introducción a los patrones de diseño" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones como este? te invito a que vea mi libro.</figcaption></figure>
<p><strong>Análisis: </strong></p>
<p>Veamos que paso.</p>
<p>En la orden no.1 se vendió un paquete llamado <strong>PC Gammer </strong>con un precio de 12,450 ,¿pero por qué cuesta eso?, si regresamos a la definición del paquete veremos que se le agregaron 6 productos simples: ram8gb($1,000), disk1tb($2,000), cpuIntel($4,500), bigCabinet(2,200), monitor30inch($2,000), gammerMouse($750), Si sumamos el precio de los 6 productos nos dará el total de 12,450 el mismo precio del paquete.</p>
<p>En la orden no.2 pasa lo mismo, se vende un paquete el cual contiene 6 productos simples pero con un precio menor.</p>
<p>La orden no.3 es un poco distinta, esta orden vende al igual que las anteriores un solo paquete, sin embargo, este paquete pc2x1 es un paquete que se creó a partir de otros dos paquetes. En este caso el total de la orden es de 22,350, pero si vemos el precio del paquete, Gammer PC($12,450) y Home PC($9,900), veremos la suma de estos dos da el precio total del paquete pc2x1($22,350).</p>
<p>Por último, tenemos la orden 4, esta orden explota al máximo el poder del patrón de diseño Composite, ya que nos permite vender paquetes y productos simples sin tener que preocuparnos de que tipo de productos es. ya que de forma <a title="Que es el Polimorfismo?" href="http://oscarblancarteblog.com/2014/07/15/que-es-el-polimorfismo/">polimorfica</a> el programa es capaz de calcular el precio de ambos tipos de productos sin necesidad de programar un trato especial.</p>
<p>Esta orden vende una Home PC($9,900), ram8gb($1,000),ram4gb(750),monitor30inch($2,000),gammerMouse(750), de los cuales Home PC es un paquete y el resto de los productos son productos simples. Si sumamos el precio de los productos veremos que el total es de 14,400.</p>
<p>Como veremos, este patrón es muy flexible con estructuras de datos compuestas, en este caso vimos que teníamos paquetes y productos simples, sin embargo, podríamos crear un tercer tipo de producto que extienda de AbstracProduct y darle el comportamiento que queramos. Otro ejemplo que le podríamos dar, es para agrupar las cuentas de un cliente, de esta forma, podríamos saber el saldo de todas las cuentes de un cliente.</p>
<p>Si te gusto este post, por favor dale me gusta y compártelo ya que esto me ayudara a crear más y mejor material.</p>
<p>Ya está a la venta mi nuevo libro &#8220;<a href="http://www.oscarblancarteblog.com/libros/introduccion-los-patrones-diseno/">Introducción a los patrones de diseño</a>&#8220;, en donde expongo los 25 patrones de diseño más utilizados y explicados desde un enfoque del mundo real, con ejemplos que pueden ser aplicados en tus proyectos. Sin duda es unos de los libros más completos de patrones de diseño en español.</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/10/07/patron-de-diseno-composite/">Patrón de diseño &#8211; Composite</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2014/10/07/patron-de-diseno-composite/feed/</wfw:commentRss>
			<slash:comments>34</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">397</post-id>	</item>
		<item>
		<title>Patrón de diseño &#8211; Proxy</title>
		<link>https://www.oscarblancarteblog.com/2014/07/29/patron-de-diseno-proxy/</link>
					<comments>https://www.oscarblancarteblog.com/2014/07/29/patron-de-diseno-proxy/#respond</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Tue, 29 Jul 2014 23:14:12 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<category><![CDATA[proxy]]></category>
		<guid isPermaLink="false">http://oscarblancarteblog.com/?p=274</guid>

					<description><![CDATA[<p>En esta entrada les hablare del patrón de diseño Proxy, el cual es uno de mis favoritos ya que nos permite hacer una gran cantidad de cosas sin que el usuario final se de cuenta de lo que esta pasando. Podríamos definir a un Proxy como una clase o componentes que hace el papel de intermediario entre [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/07/29/patron-de-diseno-proxy/">Patrón de diseño &#8211; Proxy</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/UML1-e1438565150654.gif"><img loading="lazy" class=" size-full wp-image-726 alignleft" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/UML1-e1438565150654.gif" alt="UML" width="86" height="100" /></a>En esta entrada les hablare del patrón de diseño <strong>Proxy, </strong>el cual es uno de mis favoritos ya que nos permite hacer una gran cantidad de cosas sin que el usuario final se de cuenta de lo que esta pasando. Podríamos definir a un Proxy como una clase o componentes que hace el papel de <strong>intermediario</strong> entre la clase que queremos utilizar el cliente que la esta utilizando. Cuando digo intermediario me refiero a que el Proxy nos permite hacer una o varias operaciones antes y después de realizar la tarea que realmente quiere el cliente, incluso el proxy puede tomar la decisión de nunca realizar la tarea solicitada por el usuario.</p>
<figure id="attachment_275" aria-describedby="caption-attachment-275" style="width: 411px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/patronproxy.png"><img loading="lazy" class="wp-image-275 size-full" title="Patrón de diseño Proxy" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/patronproxy.png" alt="Patrón de diseño Proxy" width="411" height="208" /></a><figcaption id="caption-attachment-275" class="wp-caption-text">Fig.1: Diagrama que muestra como esta conformado un Proxy, Un Proxy se crea a través de una interfaz la cual imita el comportamiento de esta, Sin embargo el trabajo realmente lo delega a otra clase que generalmente también implementan la interfaz del Proxy.</figcaption></figure>
<p><span id="more-274"></span></p>
<p style="text-align: justify;">Para entender bien lo que es un Proxy nos iremos al ámbito de las Redes ya que es un tema casi todos comprendemos, Todos hemos escuchado de los proxy de red o Servidores Proxy los cuales nos impiden que entremos a una determinada pagina como por ejemplo las redes sociales o paginas de vídeos en streaming. Pues bien estos servidores implementa el patrón de diseño proxy, ya que antes de enviar la solicitud a la pagina que queremos entrar primero valida si la pagina no esta en la lista de paginas bloqueadas si no es a sí entonces manda el request a la pagina y el proxy antes de enviarnos la respuesta a nuestro navegador valida por ejemplo que la pagina no tenga contenido prohibido como por ejemplo paginas de adulo o vídeo juegos, Si el proxy detecta que la respuesta de la pagina regresa un contendido de estos entonces el proxy nos manda una pagina distinta a la solicitada diciendo que la pagina tiene contenido indeseado.</p>
<p style="text-align: justify;">Los <em>proxy</em> tiene varias utilidades y podemos utilizarlo para lo que queramos, para este caso hablaremos de ejemplo prácticos los cuales son usados con regularidad.</p>
<pre><strong>Proxy de Seguridad: </strong></pre>
<p style="text-align: justify;">Cuando desarrollamos aplicaciones por lo general desarrollamos clases que utilizamos como BusinessService (Clases con operaciones de negocio) estas clases generalmente no requieren autenticación y los usuarios pueden invocar los métodos sin ningún problema, ¿pero que pasa si un día decidimos que estos métodos requieren de privilegios para ser ejecutados? una solución seria modificar los métodos para que recibieran las credenciales o modificar la aplicación para que valide los privilegios antes de mandar llamar los métodos de negocio, Sin embargo estos cambios son radicales ya que implicaría modificar la firma de los BusinessService impactando gran parte del proyecto o modificar cada parte en donde hacíamos un llamada a los BusinessService para agregar la validación antes de la llamada. Estas soluciones producirían un gran cambio en nuestra aplicación y afectaría los componentes ya desarrollados y probados para tener que volver a la etapa  de pruebas y validar nuevamente que la aplicación sigue funcionando correctamente.</p>
<figure id="attachment_279" aria-describedby="caption-attachment-279" style="width: 275px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/noproxy.png"><img loading="lazy" class="wp-image-279 size-full" title="Patrón de diseño Proxy" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/noproxy.png" alt="Patrón de diseño Proxy" width="275" height="95" /></a><figcaption id="caption-attachment-279" class="wp-caption-text">Fig.2: La figura muestra como el cliente se comunica directamente al Business Service si pasar por un Proxy lo que le da el control absoluto sobre las operaciones que quiera realizar con este.</figcaption></figure>
<p style="text-align: justify;"><strong>Solución: </strong>En vez de lo anterior podríamos envolver la ejecución del BusinessService en un Proxy el cual antes de mandar llamar al BusinessService cheque las credenciales del usuario y posteriormente invoque al BusinessService, Pero no solo eso podemos hacer, También podría mandar llamar a otro servicio de Auditoria una vez que el servicio de negocio fue invocado, esto es posible por que un proxy puede hacer algo antes y después de realizar la tarea que realmente el cliente quiere realizar, sin embargo el cliente no es consciente de lo que pasa antes y después de la invocación del BusinessService.</p>
<figure id="attachment_276" aria-describedby="caption-attachment-276" style="width: 540px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/securityproxy.png"><img loading="lazy" class="wp-image-276" title="Patrón de diseño Proxy" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/securityproxy.png" alt="Servicio de seguridad con el patrón de diseño Proxy" width="540" height="232" /></a><figcaption id="caption-attachment-276" class="wp-caption-text">Fig.3: En la figura podemos apreciar que el usuario realiza un acción sobre el proxy el cual puede realizar una tarea antes y después de realizar la tarea que el cliente, En este escenario se realiza una invocación al servicio de seguridad para validar las credenciales, después realiza la consulta al BusinessService  y por ultimo realiza la llamada a un servicio de auditoria para registrar la acción que acaba de hacer el usuario, El cliente no es consciente de la Pre-Action y la Post-Action pues el Proxy encapsula este comportamiento.</figcaption></figure>
<pre><strong>Proxy de invocación remota.</strong></pre>
<p style="text-align: justify;">Otro de los escenarios para los cuales se utilizan los proxy son para enmascarar la invocación de métodos remotos.</p>
<p style="text-align: justify;">El procedimiento para realizar esto es creando una interfaz que contenga las operaciones que queremos invocar de forma remota, Luego creamos una un Proxy a través de la interfaz la cual delegue el comportamiento a una clase que se encargue de realizar la comunicación con el servicio remoto y al final regrese lo resultados al cliente de nuestra aplicación, De esta forma la invocación remota es invisible y no se dará cuenta de que detrás del proxy existe una conexión con algún servicio remoto.</p>
<figure id="attachment_282" aria-describedby="caption-attachment-282" style="width: 512px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/remoteproxy.png"><img loading="lazy" class="wp-image-282" title="Remote Proxy" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/remoteproxy.png" alt="Remote Proxy" width="512" height="222" /></a><figcaption id="caption-attachment-282" class="wp-caption-text">Fig.4: La figura muestra como desde una aplicación podemos realizar una invocación a un servicio remoto a través de un Proxy, El Proxy delega a otra clase la lógica para la comunicación con el servicio remoto, de esta forma el cliente no se preocupa por como el servicio esta implementado si no por los parámetros que le tiene que inviar al Proxy para que funcione.</figcaption></figure>
<p>&nbsp;</p>
<p>&nbsp;</p>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="Introducción a los patrones de diseño" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones como este? te invito a que veas mi nuevo libro</figcaption></figure>
<p>&nbsp;</p>
<p style="text-align: justify;"><b>Conclusión</b><strong>:</strong></p>
<p style="text-align: justify;">En resumen podríamos decir que un <strong>Proxy</strong> es un intermediario que puede interceptar una petición y hacer algo con ella antes y después de ejecutar la operación deseada por el usuario e incluso podemos cancelar la invocación como en el caso que no tenga los privilegios.</p>
<p style="text-align: justify;">Es importante remarcar que los Proxy tiene muchas utilidades y estas que planteo a qui solo son alguno de la multitud de utilidades que tiene. Otro escenario para el cual se utilizan es para el Debug de aplicaciones de lo cual hablare en otra entrada.</p>
<p style="text-align: justify;">Ya está a la venta mi nuevo libro &#8220;<a href="http://www.oscarblancarteblog.com/libros/introduccion-los-patrones-diseno/">Introducción a los patrones de diseño</a>&#8220;, en donde expongo los 25 patrones de diseño más utilizados y explicados desde un enfoque del mundo real, con ejemplos que pueden ser aplicados en tus proyectos. Sin duda es unos de los libros más completos de patrones de diseño en español.</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/07/29/patron-de-diseno-proxy/">Patrón de diseño &#8211; Proxy</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2014/07/29/patron-de-diseno-proxy/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">274</post-id>	</item>
		<item>
		<title>Patrón de diseño Observer</title>
		<link>https://www.oscarblancarteblog.com/2014/07/23/patron-de-diseno-observer/</link>
					<comments>https://www.oscarblancarteblog.com/2014/07/23/patron-de-diseno-observer/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 23 Jul 2014 15:23:51 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[diseño]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Observer]]></category>
		<category><![CDATA[Patron]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<category><![CDATA[POO]]></category>
		<category><![CDATA[Programación orientada a objetos]]></category>
		<guid isPermaLink="false">http://javamex.wordpress.com/?p=209</guid>

					<description><![CDATA[<p>Este es sin duda uno de los patrones mas utilizados cuando trabajamos con aplicaciones de escritorio o al utilizar la Event-Driver Architecture(EDA).Un Observer es un componente el cual lo único que hace es estar atento a los eventos que el Target realiza, Cuando Target realiza un cambio o evento este notifica a todos los Observers [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/07/23/patron-de-diseno-observer/">Patrón de diseño Observer</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/UML1-e1438565150654.gif"><img loading="lazy" class=" size-full wp-image-726 alignleft" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/UML1-e1438565150654.gif" alt="UML" width="86" height="100" /></a>Este es sin duda uno de los patrones mas utilizados cuando trabajamos con aplicaciones de escritorio o al utilizar la Event-Driver Architecture(EDA).Un Observer es un componente el cual lo único que hace es estar atento a los eventos que el Target realiza, Cuando Target realiza un cambio o evento este notifica a todos los Observers que están registrados. De esta manera las clases observer serán notificadas del evento que realizo el Target.</p>
<p>&nbsp;</p>
<p>Para explicar correctamente este Patrón de diseño le comparto esta imagen:</p>
<p><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/observer.png"><img loading="lazy" class="aligncenter wp-image-208" title="Observer" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/07/observer.png" alt="Observer" width="508" height="282" /></a></p>
<p>Imaginemos un escenario de la vida real para comprender mejor esta patrón para lo cual nos ubicamos en el Aeropuerto y estamos esperando a que nos indiquen que podemos abordar el avión por medio de las bocinas que hay en el aeropuerto.</p>
<p>Bien, de seguro no eres el único que esta esperando el vuelo, de seguro existen muchas personas que esperan el abordaje, En este escenario nosotros junto con todas las demas personas que esperan el vuelo son <strong>Observers </strong>y la bocina es el <strong>Tajet </strong>Ya que todos estamos atento a que nos indique que ya podemos abordar lo cual es un evento que realiza la bocina y que nosotros estamos esperando(Observando) para realizar una acción(Abordar).<span id="more-209"></span></p>
<p>Entonces el mecanismo por el cual el observer trabaja es el siguiente:</p>
<ol>
<li>Existe un componente u Objecto al cual queremos observar(<strong>Tarjet</strong>)</li>
<li>Tenemos algún modulo u otro Objeto(<strong>Observer</strong>) el cual queremos que sea notificado cuando Tarjet realice una acción.</li>
<li>Los <strong>Observers </strong>deben <strong>implementar</strong> una <strong>Interfaz</strong> <strong>común </strong>que tanto el Target como el Observer conozcan.</li>
<li>Los Observers deberán ser registrados en el Tarjet el cual los almacenara en una lista.</li>
<li>Cuando el Tarjet realice una acción notificara a todos los Observers los cuales se registraron en el paso anterior.</li>
<li>Los Observers recibirán la notificación como un Evento el cual el Observer procesara para hacer una acción.</li>
</ol>
<p>&nbsp;</p>
<p>Si nos damos cuenta es mucho mas simple de lo que parece y muchos de las aplicaciones utilizan este patrón y ni siquiera nos damos cuenta.</p>
<p>&nbsp;</p>
<p>En tu experiencia, ¿donde crees que se mas conveniente utilizar esta patrón o como lo implementarías?</p>
<p>&nbsp;</p>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="Introducción a los patrones de diseño" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones como este? te invito a que veas mi libro.</figcaption></figure>
<p>&nbsp;</p>
<p>Ya está a la venta mi nuevo libro &#8220;<a href="http://www.oscarblancarteblog.com/libros/introduccion-los-patrones-diseno/">Introducción a los patrones de diseño</a>&#8220;, en donde expongo los 25 patrones de diseño más utilizados y explicados desde un enfoque del mundo real, con ejemplos que pueden ser aplicados en tus proyectos. Sin duda es unos de los libros más completos de patrones de diseño en español.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/07/23/patron-de-diseno-observer/">Patrón de diseño Observer</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2014/07/23/patron-de-diseno-observer/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">209</post-id>	</item>
	</channel>
</rss>
