Ejemplos de patrones de diseño

Hablemos de patrones de diseño. Vamos a describir brevemente qué son, para qué sirven, cómo se clasifican y vamos a mostrar ejemplos, en lo posible de aplicaciones reales, para mostrar su uso y aplicación.

El código fuente completo de todos los patrones de diseño en esta página se encuentra en el siguiente repositorio de Github:

Qué es un patrón

Antes de avanzar, la pregunta obligada: ¿Qué es un patrón de diseño? Según la Wikipedia, se trata de “una técnica común para resolver problemas comunes en el desarrollo de software. Tienen las siguientes características:

  • Reutilizable: que se pueda aplicar a distintas clases de problemas.
  • Efectivo: que se haya podido utilizar para resolver otros problemas.

¿Los patrones se inventan o se descubren?

Los patrones se descubren. Son soluciones comunes a ciertos problemas, lo cual no quita que puedan aparecer nuevos patrones para problemas no vistos anteriormente, o que estos sean la única manera de resolver algo. Simplemente se ofrecen para evitar la reiteración de búsqueda de soluciones y no pretenden quitar creatividad al proceso de diseño. Por último, no se debe abusar de los patrones ni es obligatorio su uso, simplemente son técnicas facilitadoras para resolver problemas.

Lista de Patrones de diseño

A continuación, esta es la lista de patrones que en este momento me acuerdo de memoria, para el resto se puede consultar la excelente referencia “Patrones de diseño” de Erich Gamma.

  • Abstract Factory
  • Adapter
  • Bridge
  • Builder
  • Command
  • Decorator
  • Factory Method
  • Memento
  • Observer
  • Prototype
  • Proxy
  • State
  • Strategy
  • Visitor

Clasificación

Existen diversas maneras de clasificar los patrones, vamos a optar por la siguiente, sacada del libro ya mencionado, y que se corresponde de cierta manera con su propósito o utilidad general.

  • Creación: Abstract factory, factory method, builder, prototype
  • Estructurales: Adapter, bridge, proxy, decorator
  • Comportamiento: command, state, memento, decorator, visitor, strategy, observer

Ejemplos: patrones de creación

Vamos a hablar de los patrones de creación. En cualquier curso de patrones de diseño, estos son los primeros que se discuten.

Factory Method

Sirve para elegir qué objetos crear de acuerdo a una condición. Parametriza la creación de objetos de una clase, de manera tal de disociar el lugar de la creación del objeto del lugar donde se usa. El creador del objeto podría escoger crear distintas clases de objeto de acuerdo a alguna lógica, y luego estos objetos ser usados sin que se conozcan detalles sobre su tipo, siempre que respeten una interfaz determinada.

Vamos a usar como ejemplo un juego de cartas. Supongamos que tengo una baraja, digamos, una baraja española, y quiero crear cartas de acuerdo a un

Diagrama

Factory Method
Factory Method

Aquí se observan los componentes de este patrón:

  • Una clase abstracta, Baraja, que declara el nombre del factory method, en este caso crearCarta
  • Una clase concreta que efectivamente implementa el factory method, en este caso BarajaEspanola
  • Una jerarquía de objetos, en este caso CartaEspanola, que son creados por el factory method
  • Una condición para crear un objeto de la jerarquía, en este caso los parámetros al factory method crearCarta, que son el palo y el número como String

La clase abstracta que declara el factory method podría no ser necesaria, pero si existieran otras barajas, digamos cartas Francesas o de poker, podrían ser distintas subclases de Baraja.

Código fuente

A continuación se muestra el código fuente:

Baraja:

package ar.strellis.ejemplospatrones.factorymethod;

public abstract class Baraja
{
	public abstract Carta crearCarta(String palo, String numero);
}

BarajaEspanola:

package ar.strellis.ejemplospatrones.factorymethod;

public class BarajaEspanola extends Baraja
{
	public enum Palo {
		OROS,
		BASTOS,
		ESPADAS,
		COPAS
	}
	public enum Numero {
		AS,
		DOS,
		TRES,
		CUATRO,
		CINCO,
		SEIS,
		SIETE,
		OCHO,
		NUEVE,
		SOTA,
		CABALLO,
		REY
	}
	@Override
	public Carta crearCarta(String palo,String numero)
	{
		return new CartaEspanola(BarajaEspanola.Palo.valueOf(palo),BarajaEspanola.Numero.valueOf(numero));
	}
}

Carta:

public interface Carta
{
}

Mazo:

package ar.strellis.ejemplospatrones.factorymethod;

public class Mazo
{
	private Baraja baraja;

	public Mazo(Baraja baraja)
	{
		this.baraja=baraja;
	}
	
	public static void main(String[] args)
	{
		Mazo m=new Mazo(new BarajaEspanola());
		m.generarCartas();
	}

	private void generarCartas()
	{
		System.out.println("Saco un rey de bastos");
		Carta carta1=baraja.crearCarta("BASTOS", "REY");
		System.out.println("Saque esta carta: "+carta1);
	}
}

En el código se observa claramente: el mazo no sabe cómo se fabrica una carta: solamente le pide a la Baraja, que se eligió de antemano, que le dé una carta con un palo y número que vienen por parámetro. A partir de ahí, el Mazo solamente trabaja con Cartas, y no importa de qué tipo de baraja sean, Española, Francesa, etc, siempre que respeten la interfaz Carta.

Be the first to comment

Leave a Reply

Your email address will not be published.


*