jueves, 7 de mayo de 2009

CREACIONALES

Abstract factory


Resumen

Este es un patrón creacional, el problema que intenta solucionar es: la creación de diferentes familias de objetos relacionados o que dependen entre si, sin especificar sus clases concretas. Permite trabajar con objetos de distintas familias de manera que las familias no se mezclen entre si y haciendo transparente el tipo de familia concreta que se esta usando.
Introducción

Se aplica principalmente a objetos. Tratan con las relaciones entre objetos, que pueden cambiarse en tiempo de ejecución y son muy dinámicos.

Clases que participan

FabricaAbstracta: Declara una interfaz para operaciones que crean objetos producto abstractos.
FabricaConcreta: Implementa las operaciones para crear objetos producto concretos.
ProductoAbstracto: Declara una interfaz para un tipo de objeto producto.
ProductoConcreto: Define un objeto producto para que sea creado por la fábrica correspondiente. Implementa la interfaz ProductoAbstracto.Cliente: Sólo usa interfaces declaradas por las clases.

Ventajas
Hace fácil el intercambio de familias de productos
Porque en el momento de que requiera lo único que se debe hacer, es cambiar o mejorar una línea de código
Fomenta la consistencia entre productos.

Encapsula la responsabilidad de creación
Porque aísla las clases concretas y ayuda a mantener un control sobre las clases de datos

Desventajas

Puede ser difícil incorporar nuevos tipos de datos.
Pero esto se puede tener solución, pasando un parámetro a los métodos de creación de productos, pero con esto sacrificaría seguridad.

Patrones relacionados

Singleton: es implementado en la fabrica concreta.
Prototype: es implementado al definir fabricas extensibles y evitar la dependencia de la interfaz de las fabricas de los nuevos productos se puede tener un catalogo de prototipos.
Factory Method: la fábrica abstracta deja que las subclases creen los productos redefiniendo las operaciones de creación.
Estructura
Codigo ejemplo
public abstract class AbstractFactory {
public abstract Disco comprarDisco();
public abstract Memoria comprarMemoria();
}

public class AmdFactory extends AbstractFactory{
public Disco comprarDisco(){
return new DiscoAmd();
}
public Memoria comprarMemoria(){
return new MemoriaAmd();
}


}
public class IntelFactory extends AbstractFactory {


public Disco comprarDisco() {
// TODO Auto-generated method stub
return new DiscoIntel();
}

public Memoria comprarMemoria() {
// TODO Auto-generated method stub
return new MemoriaIntel();
}


}
public abstract class Disco {
public abstract String getDisco();

}

public abstract class Memoria {
public abstract String getMemoria();
}

public class DiscoAmd extends Disco{

public String getDisco() {

return "Ha comprado un Disco AMD";
}

}

public class DiscoIntel extends Disco{


public String getDisco() {
// TODO Auto-generated method stub
return "Ha comprado un disco intel";
}

}
public class MemoriaAmd extends Memoria{


public String getMemoria() {
// TODO Auto-generated method stub
return "Ha comprado una memoria Amd";
}

}

public class MemoriaIntel extends Memoria{


public String getMemoria() {
// TODO Auto-generated method stub
return "Ha comprado una memoria intel";
}

}

Builder
Introducción

El objetivo es conseguir que la construcción de un objeto compuesto sea independiente de su representación, de manera que la construcción no se vea afectada por el hecho de que cambie su forma de representación.
Intención
Construir de manera flexible un objeto complejo a partir de otro objeto complejo en una serie de pasos

Motivación

Los objetos que dependen de un algoritmo tendrán que cambiar cuando el algoritmo cambia. Por lo tanto los algoritmos que estén expuestos a dicho cambio deberían ser separados, permitiendo de esta manera reutilizar algoritmos para crear diferentes representaciones.

Aplicabilidad

El patrón Builder se usa cuando:
El algoritmo para creación de un objeto complejo debe ser independiente de las partes que conforman el objeto y cómo están ensambladas.
El proceso de construcción debe permitir diferentes representaciones del objeto que se construye.

Participantes

Builder
  • Especifica una interfaz abstracta para la creación de partes de un objeto Producto.
ConcreteBuilder
  • Construye y ensambla las partes del producto por implementación de la interfaz Builder.
  • Define y guarda la ruta de la representación que crea.
  • Provee una interfaz para recuperación del producto.

Director
  • Construye un objeto usando la interfaz Builder.

Product
  • Representa el objeto complejo en construcción. El ConcreteBuilder construye la representación interna del producto y define el proceso con el cual se ensambla.
  • Incluye las clases que definen las partes componentes, incluyendo interfaces para ensamblar las partes dentro del resultado final.

Estructura


Colaboraciones

El Cliente crea el objeto Director y lo configura con el objeto Builder deseado.
El Director notifica al constructor cuándo una parte del producto se debe construir.
El Builder maneja los requerimientos desde el director y agrega partes al producto.
El Cliente recupera el producto desde el constructor.

Consecuencias

Permite variar la representación interna de un producto
• El Builder ofrece una interfaz al Director para construir un producto y encapsula la representación interna del producto y cómo se juntan sus partes.
• Si se cambia la representación interna basta con crear otro Bulider que respete la interfaz.
Separa el código de construcción del de representación
• Las clases que definen la representación interna del producto no aparecen en la interfaz del Bulider
• Cada ConcreteBuilder contiene el código para crear y juntar una clase específica de producto
• Distintos Directors pueden usar un mismo ConcreteBuilder
Da mayor control en el proceso de construcción
• Permite que el Director controle la construcción de un producto paso a paso
• Sólo cuando el producto está acabado lo recupera el director del builder
Implementación y patrones relacionados
El Builder define las operaciones para construir cada parte
• El ConcreteBuilder implementa estas operaciones
Con la Factoría Abstracta también se pueden construir objetos complejos
• Pero el objetivo del patrón Builder es construir paso a paso
• El énfasis de la Factoría Abstracta es tratar familias de objetos
El objeto construido con el patrón Builder suele ser un Composite
El Método Factoría se puede utilizar por el Builder para decidir qué clase concreta instanciar para construir el tipo de objeto deseado
El patrón Visitor permite la creación de un objeto complejo,en vez de paso a paso, dando todo de golpe como objeto visitante

Códigoejemplo

class Pizza {
private String masa = "";
private String salsa = "";
private String relleno = "";

public void setMasa(String masa) { this.masa = masa; }
public void setSalsa(String salsa) { this.salsa = salsa; }
public void setRelleno(String relleno) { this.relleno = relleno; }
}


abstract class PizzaBuilder {
protected Pizza pizza;

public Pizza getPizza() { return pizza; }
public void crearNuevaPizza() { pizza = new Pizza(); }

public abstract void buildMasa();
public abstract void buildSalsa();
public abstract void buildRelleno();
}


class HawaiPizzaBuilder extends PizzaBuilder {
public void buildMasa() { pizza.setMasa("suave"); }
public void buildSalsa() { pizza.setSalsa("dulce"); }
public void buildRelleno() { pizza.setRelleno("chorizo+alcachofas"); }
}


class PicantePizzaBuilder extends PizzaBuilder {
public void buildMasa() { pizza.setMasa("cocida"); }
public void buildSalsa() { pizza.setSalsa("picante"); }
public void buildRelleno() { pizza.setRelleno("pimienta+salchichón"); }
}



class Cocina {
private PizzaBuilder pizzaBuilder;

public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }

public void construirPizza() {
pizzaBuilder.crearNuevaPizza();
pizzaBuilder.buildMasa();
pizzaBuilder.buildSalsa();
pizzaBuilder.buildRelleno();
}
}


class BuilderExample {
public static void main(String[] args) {
Cocina cocina = new Cocina();
PizzaBuilder hawai_pizzabuilder = new HawaiPizzaBuilder();
PizzaBuilder picante_pizzabuilder = new PicantePizzaBuilder();

cocina.setPizzaBuilder( hawai_pizzabuilder );
cocina.construirPizza();

Pizza pizza = cocina.getPizza();
}
}




abstract class OtroPizzaBuilder {
protected Pizza pizza;

public Pizza getPizza() { return pizza; }
public void crearNuevaPizza() {
pizza = new Pizza();
buildMasa();
buildSalsa();
buildRelleno();
}

public abstract void buildMasa();
public abstract void buildSalsa();
public abstract void buildRelleno();
}


class OtraCocina {
private OtroPizzaBuilder pizzaBuilder;

public void setPizzaBuilder(OtroPizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }

public void construirPizza() {
pizzaBuilder.crearNuevaPizza();
//notar que no se necesita llamar a cada build.
}
}





Factory Method

Resumen

Este es un patrón que se ocupa en la creación de objetos, sin especificar la clase de objeto que se crear. Factory method se ocupa del problema mediante la definición de un método para crear los objetos.
Introducción
A veces, una aplicación en tiempo de ejecución, no puede anticipar la clase de objeto que se debe crear. La aplicación puede saber que tiene que instanciar las clases, pero solo puede saber acerca de clases abstractas, que no puede crear una instancia, Por lo tanto, la clase de aplicaciones solo puede saber cuando tiene que instanciar un nuevo objeto de una clase, no el tipo de la subclase a crear.

Intención

Definir una interfaz para crear objetos de tipo genérico permitiendo a las subclases decidir qué tipo de objetos concreto crear.

Motivación

Sea un framework para la construcción de editores de documentos de distintos tipos.
Se nos presenta el dilema de que el framework es quien sabe, a través de su clase Aplicación, cuándo se debe crear un nuevo documento, pero no sabe qué documento crear (sólo conoce a la clase abstracta o interfaz)
La solución de este dilema es encapsular el conocimiento de cuál es la subclase concreta del documento a crear y mover ese conocimiento fuera del framework.


Aplicabilidad


Una clase no puede anticipar el tipo concreto de objetos que debe crear
Una clase quiere que sus subclases especifiquen el tipo de objetos a crear

Estructura


Participantes
Product: define la interfaz de los objetos que el método factory va a crear.
ConcreteProduct: implementa la interfaz Product.
Creator: Declara el FactoryMethod(), el cual retorna un objeto del tipo Product(). Creator también puede definir una implementación por defecto del FactoryMethod() y retornar un objeto por defecto.
ConcreteCreator: Redefine el FactoryMethod() que retorna una instancia ConcreteProduct

Patrones relacionados

Template Method El patrón Factory Method es a menudo utilizado con el patrón Template Method. Prototype: El patrón Prototype proporciona un modo alternativo para un objeto de trabajar con otros objetos sin conocer los detalles de su construcción. El patrón Prototype específica la clase de objetos a crear usando una instancia prototípica, y creando los objetos mediante una copia de este prototipo.

Consecuencias

Seguir las convenciones de nombres para ayudar a otros desarrolladores a reconocer la estructura del código.
Factory method puede ser parametrizado.
Ocultar clases concretas del cliente.
Una familia de objetos tiene que ser separados por el uso compartido de la interfaz.
Una desventaja de los Factory Methods es que los clientes deberán hacer subclases de la clase creadora solo para crear un ConcreteProduct objeto particular.

Implementación

Convenios de nominación. Se suele usar el prefijo create.
La factoría se suele implementar como un Singleton.
El método fábrica parametrizado(y en menor medida el no parametrizado) protege de la variación del tipo de producto concreto.
Diseñar una fábrica concreta que permita crear productos cuya definición del tipo no se conoce en tiempo de compilación.

Código ejemplo

public abstract class Creator{
// Operación que realiza
public Product anOperation(){
Product aProduct = factoryMethod();
return aProduct;
}

protected abstract Product factoryMethod();
}
public class ConcreteCreator extends Creator{
protected Product factoryMethod() {
return new ConcreteProduct();
}
}
public interface Product{
String hacer();
}
public class ConcreteProduct implements Product{
}
public static void main(String args[]){
Creator aCreator;
aCreator = new ConcreteCreator();
aCreator.anOperation();
}


Prototype

Introducción
El objetivo es ahorrar recursos con la creación de objetos, la manera mas eficiente de tener los objetos sin crearlos de nuevo es clonándolos.
Intención
Especifica los tipos de objetos a crear utilizando una instancia prototipo, y crea nuevos objetos copiando esta instancia.
Motivación
En ciertos escenarios es preciso abstraer la lógica que decide que tipos de objetos utilizará una aplicación, de la lógica que luego usarán esos objetos en su ejecución. Los motivos de esta separación pueden ser variados, por ejemplo, puede ser que la aplicación deba basarse en alguna configuración o parámetro en tiempo de ejecución para decidir el tipo de objetos que se debe crear.
Aplicabilidad
Un sistema debe ser capaz de crear objetos sin conocer su clase exacta, como son creados, o que datos representan.
Las clases serán instanciadas sin ser conocidas por el sistema hasta el tiempo de ejecución.
Los siguientes métodos para la creación de una gran variedad de objetos son indeseables:
Las clases que inicializan la creación de objetos crean directamente los objetos. Esto hace que ellos sean conscientes y dependientes de un gran número de otras clases.
Las clases que inicializan la creación de objetos crean los objetos indirectamente a través de una clase factory method. Un factory method que es capaz de crear una gran variedad de objetos puede ser muy grande y difícil de mantener.
Las clases que inicializan la creación de objetos crean los objetos indirectamente a través de una clase abstracta factory. Para que un abstracta
factory sea capaz de crear una gran variedad de objetos debe tener una gran variedad de clases factory concretas en una jerarquía semejante a las clases que deben ser instanciadas.
Los objetos diferentes que un sistema debe crear deben ser instancias de la misma clase que contienen diferentes estados de información o datos.
Estructura

Participantes
Cliente
La clase Cliente crea nuevos objetos pidiendo al prototipo que se clone.
Prototype
Declara la interface del objeto que se clona. Suele ser una clase abstracta.
PrototypeConcreto
Las clases en este papel implementan una operación por medio de la clonación de sí mismo.

Colaboraciones
Un cliente pide a un prototipo que se clone.
Consecuencias
Un programa puede dinámicamente añadir y borrar objetos prototipo en tiempo de ejecución. Esta es una ventaja que no ofrece ninguno de los otros patrones de creación.
Esconde los nombres de los productos específicos al cliente.
El objeto cliente puede también ser capaz de crear nuevos objetos de tipos prototipo.
Se pueden especificar nuevos objetos prototipo variando los existentes.
La clase Cliente es independiente de las clases exactas de los objetos prototipo que utiliza. También, la clase Cliente no necesita conocer los detalles de cómo construir los objetos prototipo.
Los objetos de prototipo concretos implementan el interface Prototype , de esta forma el patrón Prototype se asegura de que los objetos prototipo proporcionan un conjunto consistente de métodos para que los objetos clientes los utilicen.
Se puede configurar una aplicación cargando clases dinámicamente.
No hay necesidad de organizar los objetos prototipos en ningún orden de jerarquía de clases.
Las subclases son reducidas.

Patrones relacionados

Composite
El patrón Prototype es utilizado a menudo con el patrón Composite.
Abstract Factory
El patrón Abstract Factory puede ser una buena alternativa al patrón
Prototype donde los cambios dinámicos que el patrón Prototype permite para los objetos
prototipo no son necesarios. Pueden competir en su objetivo, pero también pueden colaborar
entre sí.
Facade
La clase cliente normalmente actúa comúnmente como un facade que separa
las otras clases que participan en el patrón Prototype del resto del programa.
Factory Method
El patrón Factory Method puede ser una alternativa al patrón
Prototype cuando la paleta de objetos prototipo nunca contiene más de un objeto.
Decorator
El patrón Prototype es utilizado a menudo con el patrón Decorator.

Implementación

Todas las clases en Java heredan un método de la clase Object llamado clone. Un método clone de un objeto retorna una copia de ese objeto. Esto solamente se hace para instancias de clases que dan permiso para ser clonadas. Una clase da permiso para que su instancia sea clonada si, y solo si, ella implementa el interface Cloneable.
Si va a variar el número de prototipos se puede utilizar un administrador de prototipos.
Cómo implementar la operación clone de los objetos prototipo es otra importante característica de la implementación. Hay dos estrategias básicas para implementar la operación clone:
1. Copia superficial significa que las variables de los objetos clonados contienen los mismos valores que las variables del objeto original y que todas las referencias al objeto son a los mismos objetos. En otras palabras, la copia superficial copia solamente el objeto que será clonado, no los objetos a los que se refiere.
2. Copia profunda significa que las variables de los objetos clonados contienen los mismos valores que las variables del objeto original, excepto que estas variables que se refieren a objetos realizan copias de los objetos referenciados por el objeto original. En otras palabras, la copia profunda copia el objeto que será clonado y los objetos a los que se referencia. Implementar la copia profunda puede ser delicado.
Necesitarás decidir si quieres hacer copia profunda o superficial de los objetos copiados indirectamente. También necesitarás ser cuidadoso con el manejo de las referencias circulares.
La copia superficial es más fácil de implementar porque todas las clases heredan un método clone de la clase Object que hace esto. Sin embargo, a menos que una clase de objetos implemente el interface Cloneable, el método clone rechazará trabajar. Si todos los objetos prototipo que tu programes utilizarán clonarse a sí mismos por copia superficial, puedes ahorrar tiempo declarando un interface Prototype que extienda el interface Cloneable. De esta forma todas las clases que implementen el interface Prototype también implementarán el interface Cloneable.

Códigoejemplo
// Los productos deben implementar esta interface
public interface Producto extends Cloneable {
Object clone();
// Aqui van todas las operaciones comunes a los productos que genera la factoria
}

// Un ejemplo basico de producto
public class UnProducto implements Producto {
private int atributo;

UnProducto(int atributo) {
this.atributo = atributo;
}

public Object clone() {
return new UnProducto(this.atributo);
}

public String toString() {
return ((Integer)atributo).toString();
}
}

// La clase encargada de generar objetos a partir de los prototipos
public class FactoriaPrototipo {
private HashMap mapaObjetos;
private String nombrePorDefecto;

public FactoriaPrototipo() {
mapaObjetos = new HashMap();
// Se incluyen al mapa todos los productos prototipo
mapaObjetos.put("producto 1", new UnProducto(1));
}

public Object create() {
return create(nombrePorDefecto);
}

public Object create(String nombre) {
nombrePorDefecto = nombre;
UnProducto objeto = (UnProducto)mapaObjetos.get(nombre);
return objeto != null ? objeto.clone() : null;
}
}

public class PruebaFactoria {
static public void main(String[] args) {
FactoriaPrototipo factoria = new FactoriaPrototipo();
Producto producto = (Producto) factoria.create("producto 1");
System.out.println ("Este es el objeto creado: " + producto);
}
}
Singleton

Resumen
Este es un patrón que garantiza que una clase solo tenga una única instancia, y provee un punto de acceso global a esta, haciendo así que todos los objetos utilicen una instancia de la clase, utilicen la misma instancia.

Introducción
En las aplicaciones a veces se hace necesario acceder a un objeto único, lo primero que se piensa es, en que se necesita una variable global, pero no asegura que no podamos instanciar más de una vez un objeto de esa clase. La solución es hacer que la clase sea la responsable de controlar la existencia de una única instancia.

Intención
Garantiza que una clase sólo tenga una instancia y proporciona un punto de acceso global a ella.

Motivación

¿Cómo aseguro que una clase tenga solamente una instancia y que la instancia sea fácilmente accesible? .Una variable global hace un objeto accesible, pero no puede esperar usted de instanciar objetos múltiples. Una solución es hacer que la clase misma sea responsable de garantizar que sea instanciada una única vez. La clase puede asegurar que ninguna otra instancia puede ser creada (Interceptando los pedidos de crear nuevos objetos), y puede proveer una manera hacerlo/serlo acceda al ejemplo. Éste es el patrón Singleton.

Aplicabilidad
Deba haber exactamente una instancia de una clase y ésta deba ser accesible a los clientes desde un punto de acceso conocido.
La única instancia debería ser extensible mediante herencia y los clientes deberían ser capaces de utilizar una instancia extendida sin modificar su código.

Estructura


¿Como se crea la clase?
El constructor de la clase debe ser privado o protegido. No puede ser público.
Para almacenar nuestra instancia debemos crear un atributo que sea estático y privado. No puede ser protegido, ni público.
Hacemos un método estático de clase para crear el punto global de acceso a nuestra única instancia. Este método debe retornar la instancia única.
Participantes
Define una operación Instancia que permite que los clientes accedan a su única instancia. Instancia es una operación de clase.
Puede ser responsable de crear su única instancia.

Patrones relacionados
Puedes utilizar el patrón Singleton con muchos otros patrones. En particular, el patrón es utilizado con los patrones Abstract Factory, Builder, y Prototype.
El patrón Singleton tiene alguna similitud con el patrón Cache Management.

Consecuencias
Existe exactamente una instancia de una clase Singleton.
Otras clases que quieran una referencia a la única instancia de la clase Singleton conseguirán esa instancia llamando al método static getInstancia de la clase. Controla el acceso a la única instancia.

Tener subclases de una clase Singleton es complicado y resultan clases imperfectamente encapsuladas. Para hacer subclases de una clase Singleton, deberías tener un constructor que no sea privado. También, si quieres definir una subclase de una clase Singleton que sea también Singleton, querrás que la subclase sobrescriba el método getInstancia de la clase Singleton. Esto no será posible, ya que métodos como getInstancia deben ser static. Java no permite sobrescribir los métodos static.

Implementacion
Para forzar el carácter de una clase Singleton, debes codificar la clase de tal forma que prevengas que otras clases creen directamente instancias de la clase. El modo de realizarlo es declarar todos los constructores de la clase privados o protegidos. Tener cuidado de declarar al menos un constructor privado. Si una clase no declara ningún constructor, entonces un constructor público es automáticamente generado por ella.
Una variación común del patrón Singleton ocurre en situaciones donde la instancia de un
Singleton podría no ser necesaria. En estas situaciones, puedes posponer la creación de la Instancia hasta la primera llamada a getInstancia.
Otra variación sobre el patrón Singleton desciende del hecho de que la política de Instanciación de una clase está encapsulada en el método de la clase getInstancia. Debido a esto, es posible variar la política de creación. Una posible política es tener el método
getInstancia que retorne alternativamente una de las dos intancias o crear periódicamente una nueva instancia para ser retornada por getInstancia. Es decir se puede permitir un número variable de instancias.


Código ejemplo

public class Singleton
{
private static Singleton instance = null;

private Singleton() {}

public static Singleton GetInstance()
{
if (instance == null)
instance = new Singleton();

return instance;
}
}

No hay comentarios:

Publicar un comentario