17 diciembre 2005

Patrón factoria

Otro patrón más, el patrón factoria.

Supongamos que vamos a hacer una aplicación y en ella hay que pedir en varias ventanas (pongamos en unas 500 ventanas, para ser bestias) una fecha. Por ejemplo, si estamos haciendo una especie de agenda con listín de amigos, debemos poner fechas de las citas, fechas de los cumpleaños, fecha para alarmas, aniversarios, eventos, etc, etc.

Como somos muy hábiles programando, nos hacemos una clase EditorFecha. Además, como programamos en java, esa clase EditorFecha en un JTextField en el que se pone la fecha y le hemos añadido unos métodos dameFecha() y tomaFecha() que nos devuelven o admiten directamente un Date. De esta manera nos ahorramos la traducción de String a Date en todos los sitios.

Hacemos nuestra aplicación y en el panel/formulario que nos permite crear un nuevo amigo ponemos un "new EditorFecha()". En el panel/formulario que nos permite editar un nuevo amigo ponemos otro "new EditorFecha()". En el que nos permite añadir una nueva cita ponemos otro "new EditorFecha()", etc, etc. Así en las 500 ventanas que mencionamos al principio hacemos nuestros 500 "new EditorFecha()".

Ya contentos con nuestra aplicación que funciona estupendamente se la enseñamos a nuestro mejor amigo (habitualmente nuestro jefe que nos la ha encargado). Nuestro amigo nos dice que la aplicación es estupenda, pero que para meter la fecha es más cómodo usar la clase JCalendar que te puedes bajar gratis de internet. Esa clase tiene un botoncito que cuando le damos nos abre un calendario en el que elegimos la fecha con un click de ratón y ya está.

Nos parece buena idea, nos bajamos JCalendar y nos ponemos a cambiar código. ¡¡ Ay desgraciados de nosotros !!. Cuando hemos cambiado 133 "new EditorFecha()" por 133 "new JCalendar()" y hemos cambiado 133 "dameFecha()" por 133 "getDate()" nos hemos hartado, mandamos todo a freir espárragos. Y hemos sido demasiado pacientes, hemos llegado a cambiar 133 editores.

¿Cómo hubiera sido la forma correcta de hacer esto para que el cambio no nos suponga semejante trauma?. El patrón factoría nos da una posible solución.

Cuando preveamos que una clase puede cambiarse por otra o mejorarse (aunque sea remotamente), debemos hacerlo de la siguiente manera.

Primero hacemos una interface para esa clase con los métodos que queramos que tenga. Por ejemplo, nuestra InterfaceEditorFecha puede ser como esto

public interface InterfaceEditorFecha
{
public Date dameFecha();
publid void tomaFecha(Date unaFecha);
}

Ahora hacemos nuestro EditorFecha implementando esa interface.

Finalmente, hacemos una clase factoría con un método estático que nos de un editor nuevo cada vez que la llamemos y nos lo devuelva como esa interface. Puede ser algo como esto

public class FactoriaEditorFecha
{
public InterfaceEditorFecha dameNuevoEditor ()
{
return new EditorFecha();
}
}

Ya está. En nuestro código, en vez de hacer "new EditorFecha()", hacemos "FactoriaEditorFecha.dameNuevoEditor()" para ir construyendo nuestros editores.

Ahora viene el "amigo" del JCalendar y nos da su sabio consejo. Hacemos una clase que herede de JCalendar y que implemente nuestra interface. Los dos métodos que queremos que tenga únicamente deben hacer la traducción a los de JCalendar. Para esto existe otra cosa que se llama patrón adaptador, pero ya escribiré más adelante sobre él.

public class MiJCalendar extends JCalendar implements InterfaceEditorFecha
{

public void tomaFecha (Date unaFecha)
{
this.setDate(unaFecha);
}

public Date dameFecha ()
{
return this.getDate();
}

}

y simplemente cambiando en nuestra clase FactoriaEditorFecha el "new EditorFecha()" por "new MiJCalendar()" ya tenemos TODA la aplicación cambiada.

En realidad el patrón factoría es algo más complejo y permite incluso cambiar el new que hace sin necesidad de tocar el código de la clase Factoría, pero ya me parece liar mucho para un primer vistazo.

Una cosa importante, JCalendar existe, pero me he inventado sus métodos por pereza y por simplificar un poco.