Anda di halaman 1dari 19

Despus de la breve introduccin a los patrones de diseo, llega el momento

de explicar los patrones de diseo creacionales.

Los patrones de diseo creacionales se centran en resolver problemas acerca


de cmo crear instancias de las clases de nuestra aplicacin. A continuacin
nos centraremos en cada uno de ellos.

para abrir losl archivos .fla es necesario Adoble Flash Professional CS4 o
superior

Abstract Factory
El patrn Abstract Factory o Fbrica Abstracta resuelve el problema de crear
familias de objetos. Veamos un ejemplo tpico de este patrn:

Imaginemos que estamos trabajando con Interfaces Grficas de Usuario (GUI).


Pensemos que, en nuestro programa, tenemos las clases Ventana y Boton.
Pongamos, por ejemplo, que tenemos 2 interfaces diferentes: una con colores
claros y otra con colores oscuros. Esto nos llevara a tener 4 clases:

VentanaClara
VentanaOscura
BotonClaro
BotonOscuro

Cuando el usuario decida trabajar con colores claros, se deben crear instancias
de VentanaClara y BotonClaro. Sin embargo, si el usuario decide utilizar la
interfaz de colores oscuros, deberamos crear instancias
de VentanaOscura y BotonOscuro. La forma ms bsica de hacerlo sera de
esta manera:

Cdigo :

// A la hora de seleccionar la interfaz

var GUI:String = "clara"; // u "oscura";

// A la hora de crear un botn

if(GUI == "clara"){

new BotonClaro();

}else if(GUI == "oscura"){


new BotonOscuro();

// A la hora de crear una ventana

if(GUI == "clara"){

new VentanaClara();

}else if(GUI == "oscura"){

new VentanaOscura();

Esto implicara realizar una comprobacin de la interfaz seleccionada cada vez


que se quiera crear una Ventana o un Boton.

La mejor opcin en este caso sera utilizar el patrn Abstract Factory.

En este patrn se crean ciertas clases adicionales llamadas fbricas. Estas


clases son las encargadas de crear los diferentes tipos de ventanas y botones.
Veamos un ejemplo de su estructura:

Click en la imagen para ver en tamao original

Identifiquemos cada clase del diagrama con las clases de nuestro ejemplo:

Cliente: Parte del programa que utilizar las fbricas y productos. Podra ser el
archivo .fla principal, por ejemplo.
IProductoA: Interfaz que define un ejemplo de producto. Se correspondera
con la clase Ventana de nuestro ejemplo.
ProductoA1 y ProductoA2: Los diferentes tipos de ese producto. Se
corresponderan con la clases VentanaClara y VentanaOscura.
IProductoB: Interfaz que define otro ejemplo de producto. Se correspondera
con la clase Boton de nuestro ejemplo.
ProductoB1 y ProductoB2: Los diferentes tipos de ese producto. Se
corresponderan con la clases BotonClaro y BotonOscuro.
IFabrica: Interfaz que define las funciones de creacin de productos. En
nuestro ejemplo podra llamarse InterfazGrafica y definira las
funciones crearVentana():Ventana y crearBoton():Boton.
Fabrica1 y Fabrica2: Clases encargadas de crear los productos. En nuestro
ejemplo, seran InterfazClara (que creara instancias
de VentanaClara y BotonClaro) e InterfazOscura (que creara instancias
de VentanaOscura y BotonOscuro).

Cabe sealar que podra haber ms tipos de productos


(Ventana, Boton, Icono, etc.) y ms familias de estos
(InterfazClara, InterfazOscura, InterfazAzul, InterfazRoja, etc.).

Una vez utilizado el patrn, el cdigo anterior quedara as:

Cdigo :

// A la hora de seleccionar la interfaz

var GUI:InterfazGrafica = new InterfazClara(); // o new


InterfazOscura();

// A la hora de crear un botn

GUI.crearBoton();

// A la hora de crear una ventana

GUI.crearVentana();

Segn el tipo de InterfazGrafica instanciada, se crearn ventanas/botones de


un tipo u otro dinmicamente, sin necesidad de comprobar a mano qu interfaz
grfica se est utilizando.

Descargar archivos de ejemplo Abstract Factory

Builder
El patrn Builder o Constructor se utiliza cuando queremos crear un producto
que tiene diferentes partes. El siguiente ejemplo, basado en este otro, lo ilustra
mejor:

Imaginemos la cocina de una pizzera donde se hacen pizzas. Las pizzas


constan de varias partes (masa, salsa y relleno), y podramos tener 2
cocineros, cada uno especialista en un tipo de pizza. Esto nos llevara a tener 5
clases:

Cocina
Pizza
Cocinero
CocineroHawai
CocineroPicante

En una situacin como esta el patrn Builder nos puede ayudar. Veamos un
ejemplo de su estructura:

Click en la imagen para ver en tamao original

Identifiquemos cada clase del diagrama con las clases de nuestro ejemplo:

Cliente: Parte del programa que utilizar el resto de clases. Podra ser el
archivo .fla principal, por ejemplo.
Director: Clase que decide qu constructor se utiliza y cuando se debe
construir el producto. Se correspondera con la clase Cocina de nuestro
ejemplo.
IConstructor: Interfaz que define las funciones de creacin de cada parte del
producto y la funcin de obtencin del producto resultante. En nuestro ejemplo
se correspondera con Cocinero y definira las
funciones hacerMasa():void, utilizarSalsa():void y hacerRelleno():void.
Constructor1 y Constructor2: Clases encargadas de crear las partes del
producto. En nuestro ejemplo, seran CocineroHawai y CocineroPicante.
Producto: Clase del producto en s. Se correspondera con la clase Pizza de
nuestro ejemplo.

De esta manera, un posible cdigo de este ejemplo sera el siguiente:

Cdigo :

var cocina:Cocina = new Cocina();

// Decidimos que se crearn pizzas hawaianas

cocina.elegirCocinero(new CocineroHawai());

// Creamos la pizza

var pizzaHawaiana:Pizza = cocina.nuevaPizza();

El cdigo de la clase Cocina podra ser algo as:

Cdigo :

package {

public class Cocina {

private var cocinero:Cocinero;

public function elegirCocinero(cocinero:Cocinero):void {

this.cocinero = cocinero;

}
public function nuevaPizza():Pizza {

cocinero.hacerMasa();

cocinero.utilizarSalsa();

cocinero.hacerRelleno();

Opcionalmente podra definirse un constructor para la clase Cocina que


recibiese el cocinero como argumento, ahorrando la llamada a elegirCocinero().

Descargar archivos de ejemplo Builder

Factory Method
El patrn Factory Method o Mtodo de Fbrica es una simplificacin del
patrn Abstract Factory. En un patrn Factory Method slo existe un
producto, no una familia de ellos. Veamos un ejemplo donde yo mismo he
utilizado este patrn:

Imaginemos que deseamos crear un juego estilo Tetris. En este juego


tendramos diferentes tipos de piezas. Esto nos llevara a tener una clase por
cada tipo de pieza:

PiezaL
PiezaT
PiezaI
...

Cada vez que se crea una pieza nueva, desearamos seleccionar el tipo de
pieza de forma aleatoria. La forma ms bsica de hacerlo sera la siguiente:

Cdigo :

// Seleccionaramos el tipo de pieza aleatoriamente


var tipo:uint = Math.random()*7; // 7 es el nmero de
piezas diferentes en el Tetris

// Creamos dicha pieza

switch(tipo){

case 1:

new PiezaL();

break;

case 2:

new PiezaT();

break;

case 3:

new PiezaI();

break;

// ...

Sin embargo, sera mucho ms sencillo poder hacerlo de una manera parecida
a esta:

Cdigo :

// Seleccionaramos el tipo de pieza aleatoriamente

var tipo:uint = Math.random()*7; // 7 es el nmero de


piezas diferentes en el Tetris

// Creamos dicha pieza

new Pieza[tipo]();
Para poder hacer algo as debemos utilizar el patrn Factory Method.

En este patrn se utilizan fbricas, al igual que en el patrn Abstract Factory.


Estas fbricas son las encargadas de crear los diferentes tipos de piezas.
Veamos un ejemplo de su estructura:

Click en la imagen para ver en tamao original

Identifiquemos cada clase del diagrama con las clases de nuestro ejemplo:

Cliente: Parte del programa que utilizar las fbricas y productos. Podra ser el
archivo .fla principal, por ejemplo.
IProducto: Interfaz que define el producto. Se correspondera con una
clase Pieza en nuestro ejemplo.
ProductoA y ProductoB: Los diferentes tipos del producto. Se
corresponderan con la clases PiezaL, PiezaT y PiezaI.
IFabrica: Interfaz que define las funcin de creacin del producto. En nuestro
ejemplo podra llamarse ICreador y definira la funcin crearPieza():Pieza.
FabricaA y FabricaB: Clases encargadas de crear los productos. En nuestro
ejemplo, seran CreadorL (que creara instancias de PiezaI), CreadorT(que
creara instancias de PiezaT), CreadorI (que creara instancias de PiezaI), etc.

Una vez utilizado el patrn, el cdigo anterior quedara as:

Cdigo :

// Crearamos una lista con todas las fbricas

var creadores:Vector.<ICreador> = new Vector.<ICreador>();

creadores.push(new CreadorL(), new CreadorT(), new


CreadorI());

// Seleccionaramos el tipo de pieza aleatoriamente

var tipo:uint = Math.random()*7; // 7 es el nmero de


piezas diferentes en el Tetris
// Creamos dicha pieza

creadores[i].crearPieza();

De esta manera no necesitaramos un switch, sino que se creara la pieza a


travs del creador seleccionado.

Descargar archivos de ejemplo Factory Method

Prototype
El patrn Prototype o Prototipo resuelve el problema de duplicar objetos ya
creados con anterioridad. Veamos un pequeo ejemplo de este patrn:

Imaginemos que tenemos un programa de dibujo por ordenador en el cual


podemos crear crculos y cuadrados. Cuando se crea un crculo, ste tiene un
radio de 50 pxeles y es de color rojo. Sin embargo, podemos redimensionar el
crculo y cambiar su color. Cuando se crea un cuadrado, tiene 50 pxeles de
lado y es de color azul. Hasta aqu todo perfecto.

Imaginemos ahora que el usuario decide crear un crculo y modifica su color y


tamao. Acto seguido, el usuario decide hacer una copia de dicho crculo. El
cdigo sera el siguiente:

Cdigo :

var circuloNuevo:Circulo = new Circulo();

circuloNuevo.color = circuloExistente.getColor();

circuloNuevo.radio = circuloExistente.getRadio();

Uno de los problemas ms inmediatos de hacerlo de esta manera es que, si se


aaden nuevos atributos a la clase Circulo, habra que modificar el cdigo en
cada lugar donde se haya hecho una copia de un Circulo.

El patrn Prototype aade un mtodo que permita crear una copia de un


objeto. Veamos un ejemplo de su estructura:
Identifiquemos cada clase del diagrama con las clases de nuestro ejemplo:

Cliente: Parte del programa que utilizar las fbricas y productos. Podra ser el
archivo .fla principal, por ejemplo.
IPrototipo: Interfaz que define el mtodo clonar():IPrototipo. En nuestro
ejemplo podra ser una clase llamada IObjetoGrafico.
Prototipo1 y Prototipo2: Las diferentes clases que implementarn el mtodo
de clonacin. Se corresponderan con la clases Circulo y Cuadrado de
nuestro ejemplo.

Una vez utilizado el patrn, el cdigo anterior quedara as:

Cdigo :

var circuloNuevo:Circulo = circuloExistente.clonar();

Si ahora quisiramos aadir nuevos atributos a la clase Circulo, slo habra


que modificar el mtodo clonar():IPrototipo de la clase Circulo.

Por ltimo, debe saberse que hay 2 tipos de clonacin de


objetos: profunda y superficial. Imaginemos un objeto A que contenga una
referencia a un objeto B. Una clonacin profunda hara que la copia del objeto
A referenciase a una copia del objeto B. Por el contrario, una clonacin
superficial hara que la copia del objeto A apuntase al mismo objeto B que el
objeto A original. Esto se entiende mejor con este ejemplo grfico.

Descargar archivos de ejemplo Prototype


Singleton
El patrn Singleton se utiliza para no permitir que existan mltiples instancias
de una clase, sino solamente una. Veamos un pequeo ejemplo de este patrn:

Imaginemos un programa que, al hacer click en un icono de ayuda, cree una


ventana nueva con los documentos de ayuda del programa. Normalmente, si el
usuario hiciese click en el botn nuevamente, se abrira una nueva ventana, y
as sucesivamente.

Sin embargo, podramos desear que, si la ventana de ayuda ya ha sido abierta,


no se abra de nuevo. Para ello recurriramos a un patrn Singleton, que
asegurara la existencia de una nica ventana de ayuda en todo momento.

Veamos un ejemplo de la estructura del patrn Singleton:

Identifiquemos cada clase del diagrama con las clases de nuestro ejemplo:

Cliente: Parte del programa que utilizar las fbricas y productos. Podra ser el
archivo .fla principal, por ejemplo.
Singleton: Clase que se quiere instanciar una sola vez. Se corresponde con la
clase VentanaAyuda de nuestro ejemplo.

La forma de implementar el patrn Singleton en este ejemplo sera dotando a la


clase VentanaAyuda de un mtodo esttico getInstancia():VentanaAyuda que
comprobase si ya existe una instancia VentanaAyuda o si, por el contrario, se
debe crear. De esta manera, el cdigo para crear una nueva VentanaAyuda
sera el siguiente:

Cdigo :

var ayuda:VentanaAyuda = VentanaAyuda.getInstancia();

Sin embargo, debemos evitar que el usuario pueda crear instancias de


VentanaAyuda mediante el constructor new VentanaAyuda(). La forma idnea
de hacerlo es declarando el constructor como privado, de modo que no pueda
ser llamado desde fuera de la clase VentanaAyuda. El problema es que
ActionScript, de momento, no permite la declaracin de constructores privados.
Podemos solucionarlo de la siguiente manera:

Cdigo :

package {

public class VentanaAyuda{

// Esta variable guardar la nica instancia de sta clase

// que existir en el programa

private static var instancia:VentanaAyuda;

// sta variable servir para saber cundo el constructor

// es invocado desde fuera de la clase

private static var llamadaInterna:Boolean;

// Constructor

public function VentanaAyuda(){

// Comprobamos si la llamada se ha producido

// desde fuera de esta clase

if (!llamadaInterna){

// Si se ha intentado instanciar la clase desde el

// exterior, la aplicacin devolver un error y no

// se crear ninguna instancia de VentanaAyuda.


throw new Error("Debes usar getInstancia()");

// Mtodo que instanciar la clase una sola vez

public static function getInstancia():VentanaAyuda {

// Comprobamos si la instancia no se ha creado todava

if (instancia == null) {

// Especificamos que la llamada

// al constructor es interna

llamadaInterna = true;

// Guardamos en la variable "instancia"

// una instancia de esta clase

instancia = new VentanaAyuda();

// Especificamos que las llamadas

// posteriores no sern internas

llamadaInterna = false;
}

// Por ltimo, devolvemos la instancia existente

return instancia;

Observemos ahora el efecto que producira este cdigo de ejemplo:

Cdigo :

new VentanaAyuda(); // Se devolvera un error y no se


instanciara la ventana

VentanaAyuda.getInstancia(); // Se devolvera una nueva


instancia de VentanaAyuda

VentanaAyuda.getInstancia(); // Se devolvera la instancia


ya existente que se cre en la linea anterior

Descargar archivos de ejemplo Singleton

Sabes SQL? No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y


ms con el Curso Profesional de Bases de Datos que empieza el martes, en
vivo.

Envia un comentario (18)

Nuevos patrones de diseo para POO en Actionscript 3

Singleton y funciones estticas en AS3


POO: Dependencia de clases y Polimorfismo

Por Biktor el 18 de Agosto de 2011

Esto si que es un tutorial

Lo tengo que leer mas despacio... pero una primera lectura me ha aclarado un montn de cosas y
eso que no es fcil transmitir este tipo de conceptos y currarselos para que sean accesible.

Los Patrones de Diseo


Hoy: Patrones
Creacionales
5 diciembre 2016 | Juan Mara Hernndez | c#, design patterns
Todo desarrollador que se precie debera conocer los patrones de diseo, y
especialmente los clsicos de la GoF. Aunque vivieron su momento de hype,
siguen siendo tiles a la hora de desarrollar, sobre todo porque facilitan mucho la
comunicacin entre desarrolladores al poder estandarizar el nombre las cosas.
Teniendo en cuenta que el libro que origin todo esto es de 1994 y que en estos
ltimos 22 aos los lenguajes y estilos de programacin han tenido su evolucin,
he pensado que podra ser entrenido ver qu tal ha aguantado el paso del tiempo
cada patrn de los 23 que aparecan en el catlogo original. Como son unos
cuantos, voy a dividirlo en 3 posts, siguiendo las categoras que aparecen en el
propio libro: patrones creacionales, patrones estructurales y patrones de
comportamiento.
Todo esto es bastante personal y depende mucho del estilo de programacin de
cada uno y de los lenguajes que utilice, as que no te lo tomes como algo
excesivamente serio. De hecho, en este post hay un claro sesgo hacia lenguajes
orientados a objetos porque, como todos sabis, en programacin funcional todos
los problemas de diseo se solucionan con funciones ;-)
No voy a entrar en detalle a describir cada patrn porque para eso ya hay miles
de pginas en internet. Si no los conoces, te recomiendo que hagas una bsqueda
rpida porque merece la pena que, por lo menos, te suenen.

Empezamos con los patrones creacionales.

Abstract Factory
Si necesitas tener distintas implementaciones de una factora para generar
distintas familias de clases, probablemente tu arquitectura sea demasiado
complicada. En serio, tener un AbstractMembershipProviderFactory que
sirve para abstraer las distintas implementaciones de factoras capaces de crear
distintas implementaciones de MembershipProvider es como para detenerse a
pensar si realmente te hacen falta tantos grados de indireccin.
Ojo, no hay que confundir este patrn con el patrn factory (sin el abstract),
donde tenemos un objeto (la factora) que es capaz de crear distintos de objetos o
incluso distintas configuraciones de un mismo objeto. Este patrn tiene muchos
ms usos y es rara la aplicacin medianamente compleja en la que no aparece
varias veces.

Aplicando el patrn factory (sin el abstract) en un par de puntos concretos de la


aplicacin, muchas veces te puedes ahorrar montar todo el sistema completo de
inyeccin de dependencias con un contenedor y conseguir resultados similares
con un cdigo mucho ms sencillo de seguir.
Utilidad hoy en da: 2 con abstract, 5 sin abstract.

Builder
Un patrn al que me cost mucho tiempo verle la utilidad real, pero que ha
encontrado un hueco muy importante en mi estilo de programacin a la hora de
escribir tests.
Otro escenario en el que se utiliza bastante es al disear interfaces fluidos de esos
que estaban tan de moda hace 8 aos. Me gusta especialmente cuando se usa para
preparar la construccin de la configuracin que se usar luego en tiempo de
ejecucin, al estilo de lo que se hace con Fluent NHibernate o con el IAppBuilder
de OWIN.
Saliendo de esos dos escenarios, tests e interfaces fluidos, la verdad es que no lo
uso demasiado. Es raro que construya tantas veces un mismo tipo de objeto y con
tantas configuraciones diferentes como para que me compense montar un builder.

Utilidad hoy en da: 3.

Factory Method
La definicin original de factory method nunca me ha acabado de convencer. De
hecho, la diferencia con template method es realmente stil (esto pasa con ms
patrones), ya que consiste en tener un mtodo abstracto o virtual en una clase
base para construir algo, y dejar que las clases derivadas decidan exactamente
qu y como implementar.

Aunque eso tiene sus usos, hay otra forma de ver el factory method que s utilizo
ms y me parece ms prctica: tener un mtodo esttico que construye objetos. A
diferencia de un factory, que es una clase entera dedicada a construir cosas, aqu
tenemos uno o ms mtodo estticos para construirlas, y estos mtodos residen
generalmente en la clase base de la jerarqua de clases que estamos construyendo.
Un ejemplo es SymmetricAlgorithm.Create o WebRequest.Create.
Lo utilizo bastante para poder simular constructores con nombre y que quede
ms claro lo que estoy creado. Por
ejemplo, Color.FromRGB y Color.FromHexString,
o Result.Success(value) y Result.Error(exception).
Utilidad hoy en da: 2 (el factory/template method original), 4 (el factory
method as named constructor).

Prototype
Si nos ceimos nicamente a clonar objetos, que es lo que dice el patrn original,
la cosa se queda un poco triste. Si ampliamos la idea a construir objetos a partir
de otros con las modificaciones que queramos, se hace ms interesante. Puede
parecer que no se usa mucho, y tal vez en C# sea as, pero hay otros lenguajes en
lo que resulta muy habitual.

En Javascript se utiliza continuamente, y no me refiero a la herencia


prototpica que casi nadie aprovecha conscientemente, sino a esto:
1 var opts = Object.assign({}, defaultOpts, customOpts)
Clonando el objeto defaultOps y modificndolo con el contenido
de customOptscreamos las opciones reales.
Tambin es habitual verlo en lenguajes que favorecen el uso de estructuras de
datos inmutables, donde partiendo de una estructura que sirve de base, se clona
(en realidad se reutiliza, aprovechando su inmutabilidad) y sirve de base para
crear la siguiente versin de la estructura.

Utilidad hoy en da: 3.

Singleton
El pobre singleton. Creo que fue el primer patrn de diseo que conoc y entend
(al igual que mucha gente). De ah al abuso bueno, ya sabemos todos como
acab el singleton.

Pese a su mala fama, sigue teniendo su uso y, al igual que ocurre con los mtodos
estticos, se pueden salvar muchos de sus problemas. Aun as, su utilidad es
limitada y suelo preferir separar la gestin del ciclo de vida de la clase de la
propia clase, dejando que sea otro el que lo gestione.
En general, antes de utilizar un singleton prefiero utilizar una fachada esttica.
Pierdes la parte de la inicializacin perezosa, pero te ahorras algo de cdigo al no
tener que andar poniendo el Instance o getInstance() por todas partes.
Utilidad hoy en da: 2.

Conclusin
En este post hemos repasado los 5 patrones creacionales clsicos y, en conjunto,
podramos decir que gozan de una salud bastante razonable, y ms teniendo en
cuenta que vienen de una poca en la que no exista ni Java.

Algunos de ellos como AbstractFactory y Singleton han cado ms en desuso, en


parte por sus propios defectos (excesiva complejidad o excesivo acoplamiento),
pero tambin porque cuando los contenedores de inversin de control se
hicieron mainstream parte de las problemas que solucionaban estos patrones
quedaban resueltos por el propio contenedor.
Las factoras (no abstract) y los factory methods (como constructores estticos)
son dos patrones que utilizo con mucha frecuencia y creo que aportan bastante en
forma de abstraccin y legibilidad al tratar con jerarquas de clases, o incluso con
una nica clase cuando queremos resaltar muy bien las caractersticas de la
instancia que estamos construyendo.

Builder y Prototype son dos patrones de uso ms limitado. Cuando son tiles,
resultan muy tiles, pero lo cierto es que no los utilizo con tanta frecuencia.

inShare32
Posts relacionados:
1. Patrones de Reutilizacin de Cdigo entre Componentes de ReactJS
2. Parece lo mismo pero
3. Diseo por Contrato

Anda mungkin juga menyukai