Unos post más atrás (si no recuerdo mal hablando de .NET Remoting) surgió en la conversación el patrón Faí§ade. Es más,incluso se adjuntó un diagrama de arquitectura donde veíamos implementado el patrón dando vida a la convivencia de servicios web y servicios de remoting en la misma arquitectura.
En su día prometí dedicar un post al patrón Faí§ade, pero como este implementa otro patrón llamado Factory, creo que mejor antes vamos a por el Factory para luego atacar Faí§ade con un poco más de base.
El patrón Factory entra en el grupo de patrones de creación (donde también podemos encontrar Singleton del cual ya hemos hablado también en otros post). Los patrones de creación, tal como su nombre indica, se dedica a crear objetos y a encapsular dicha creación para abstraernos de la misma (lo de siempre quitar trabajo, elevar la productividad y la mantenibilidad).
Os dejo aquí un PDF interesante al respecto de los patrones de creación por si os interesa el tema a fondo, vienen bastantes ejemplos.
https://www.dei.inf.uc3m.es/docencia/p_s_ciclo/tdp/curso0203/apuntes/factory.pdf
De todas maneras, lo de siempre, yo os voy a dejar una muestra muy pequeña que os sirva de punto de partida y ya luego si os interesa a fondo os metéis a saco teniendo la base ya firme.
Antes de empezar, contaros que hay tres tipos de patrones Factory: Simple Factory, Factory Method y Abstract Factory y aquí en principio sólo vamos a hablar de Simple Factory ya que es el patrón que usa Faí§ade, que es a lo que queremos llegar.
Aprovecho y hago un inciso, es importante en esta profesión centrarse en el problema y no irse por las ramas, si sabéis que algo soluciona vuestro problema, a por ello, no os pongáis a mirar y mirar y mirar, porque el tiempo se os va a ir y la fecha de entrega de un proyecto suele ser fija 🙂 Fin del inciso.
Factoría Simple + Strategy (mira tíº por donde nos aparece otro patrón)
Allí va un ejemplo, a ver si quedan las cosas claras.
Primero una interfaz Vehículo (código C#):
public interface Vehiculo
{
public void Arrancar();
public void Frenar();
public void GirarIzquierda();
public void GirarDerecha();
}
Como véis la interfaz vehículo lo que hace es definir una serie de comportamientos comunes a cualquier vehículo.
Ahora implementemos dos vehículos.
public class Coche : Vehiculo
{
public void Arrancar()
{
// Código necesario para arrancar el coche.
}
… Resto de métodos de Vehículo …
}
public class Moto : Vehiculo
{
public void Arrancar()
{
// Código necesario para arrancar la moto
// que no es igual al del coche claro
}
… Resto de métodos de Vehículo …
}
Como véis lo íºnico que hemos hecho aquí es implementar los métodos de un vehículo para un coche y una moto. Hemos definido cómo actíºan cada uno por separado. Hemos encapsulado dicho comportamiento en las clases que heredan de vehículo.
Y ahora ya “la magia”, la factoría que genera vehículos:
public class FactoriaVehiculo
{
public static Vehiculo GetVehiculo (TipoEnumeradoVehiculo vehiculo)
{
switch (TipoEnumeradoVehiculo)
{
case vehiculo.Coche:
return new Coche();
break;
case vehiculo.Moto:
return new Moto();
break;
default:
return null;
break;
}
}
}
Hemos utilizado un Tipo Enumerado auxiliar para hacer esto más legible y sobre todo más encapsulado. Otra opción era pasarle a GetVehículo un String… pero claro, estamos en lo de siempre, si le pasamos un string estamos dando por hecho que sabemos que hace por dentro la factoría, cuando no tiene por qué ser así.
Bien, por íºltimo, vamos a crear un procedimiento que utilice la factoría, para así acabar de darle forma al asunto:
public void EjemploFactoria()
{
// lista genérica, SIEMPRE QUE SEA POSIBLE
List<Vehiculo> listaVehiculos = new List<Vehiculo>;
// añadimos vehículos a la lista genérica
listaVehiculos.add(FactoriaVehiculo.GetVehiculo((TipoEnumeradoVehiculo.Coche));
listaVehiculos.add(FactoriaVehiculo.GetVehiculo((TipoEnumeradoVehiculo.Moto));
listaVehiculos.add(FactoriaVehiculo.GetVehiculo((TipoEnumeradoVehiculo.MotoConSidecar));
listaVehiculos.add(FactoriaVehiculo.GetVehiculo((TipoEnumeradoVehiculo.TodoTerreno));
// recorremos la lista de vehículos
foreach (Vehiculo unVehiculo in listaVehiculos)
{
unVehiculo.Arrancar();
}
}
¿Queda claro? La factoría ha ocultado cómo se crean las clases y las ha devuelto ya generadas. Por cierto, hemos hablado antes del patrón Strategy… ¿pero dónde aparece? Pues lo vemos en funcionamiento en la línea unVehiculo.Arrancar(). Cada vehículo arrancará como tenga definido, esa es su estrategia. Strategy es un patrón muy simple y que seguramente habréis implementado muchas veces pero sin haberlo llamado nunca así 🙂 Os dejo el link de la wikipedia al respecto aquí para que le echéis un ojo.
Por cierto, menudo ejemplo de polimorfismo nos ha salido también, ¿no? Ahora que caigo, ¿podríamos definir el polimorfismo como sinónimo de patrón strategy? Tengo que investigarlo.
Más cosas también para terminar, en otros posts también se habló de crear factorías de DAO’s, ¿se ve ahora un poco mejor el tema?
¡Saludos a todos y feliz navidad!
Miguel.
Hola!
Interesante el post. Creo que hay un error, que por lo menos, a mi me hizo darle una vuelta, pero solo es un detalle. Es la siguiente linea
listaVehiculos.add(FactoriaVehiculo.GetJuego((TipoEnumeradoVehiculo.Coche));
creo que deberias reemplazarla por esta.
listaVehiculos.add(FactoriaVehiculo.GetVehiculo((TipoEnumeradoVehiculo.Coche));
Saludos!
Roberto
Efectivamente Roberto, tienes toda la razón, debería poner GetVehiculo.
Lo actualizo.
Muchas gracias.
Miguel.
“Somos ingenieros y nos gusta aprender, pero no nos podemos pasar el día aprendiendo sin dar un resultado porque si no no seríamos ingenieros, seríamos científicos”. Eso ofende, ¿sabes? No sé de dónde sacaste que los científicos no producimos resultados, pero sería agradable que investigaras un poco y vieras que muchos adelantos no fueron por accidente o por la inteligente intervención de las amas de casa.
C, tienes toda la razón del mundo, no ha sido una afirmación demasiado acertada por mi parte.
La afirmación viene del dicho que “La diferencia entre un ingeniero y un científico es que un ingeniero aprende para trabajar y un científico trabaja para aprender”, afirmación que, claro está, no he sabido trasladar de forma muy correcta a la forma del post.
Te agradezco la puntualización.
Un saludo.
Miguel.
Creo que debo pedirte disculpas. Ahora que leo lo que dije, tengo la impresión de que fui un poco beligerante. Roberto me explicó qué quería decir y te diré lo mismo: los científicos amamos tanto el camino para descubrir algo, como el descubrimiento en sí mismo. Y tienes razón en que a veces nos detenemos demasiado tiempo a mirar el paisaje. 🙂
Gracias por las aportaciones C 🙂
Un saludo.
Miguel.
Muy Buenas Miguel.
El articulo es bueno, deja claro la utilizacion de un patron sin requerir a un esquema UML, que son muy claros pero el codigo es para mi el mejor vehiculo para entender un articulo de este tipo.
Creo que el patron factory es muy similar al patron fachade, ya que el fachade se encarga de implementar varias interfaces distintas partiendo de una interfaz base, y ser la interfaz base la unica visible para el cliente, abstrayendole de la complejidad de la implementacion de las interfaces heredadas de la base.
Solo me surge una curiosidad si existen 3 metodos que hacen lo mismo en distintas clases que heredan de la base. ¿como hacemos para no duplicar el codigo?
Gracias por aportar tus conocimientos a la sociedad.
Soy Ingeniero Informatico y llevaba bastante tiempo detras de un site que se basara en patrones de diseño con ejemplos claros y concisos. Solo queria darte las gracias porque he leido la mayoria y estan de puta madre.
Aprovecho para responder tanto a NetEitor como a Juan Carlos.
NetEitor:
Si hace exactamente lo mismo para los tres hijos, incorpora el método en la clase padre, así no repetirás el código. Otra cosa es que no quieras que un cuarto hijo tenga visibilidad sobre dicho método… ahí ya tendrías que recurrir a otras soluciones.
Juan Carlos:
Gracias a ti, cualquier aportación que quieras hacer al respecto será más que bienvenida.
Un saludo a los dos.
Miguel.