Patrones de Diseño - Patron Decorator/Decorador - ¿Que es el Patrón de Diseño Decorator?

Hace miles de año cuando empece este blog, una de la ideas iniciales era comenzar con los patrones de diseño, si bien en una publicación de hace mucho tiempo identifique los patrones de diseño (acá) nunca entramos en detalle, pero bueno el tiempo nos pasa para otros así que es hora que comencemos con ellos, hoy vamos a ver el Patron Decorator/Decorador


Patrones de  Diseño -  ¿Que es el Patrón de Diseño Decorator?

El Patrón Decorator  es un patrón que permite agregar funcionalidades y responsabilidades a objetos de forma dinámica y transparente para el usuario, proporcionando una alternativa flexible a la herencia para extender funcionalidad.

Diagrama UML


Patrones de  Diseño -  ¿Que es el Patrón de Diseño Decorator?

Component: Clase abstracta que define los métodos que tendrá en común los componentes.
ConcreteComponent: Clase la cual extiende del componente e implementa sus métodos.
Decorador: Acá esta la magia, El decorator extiende el component y aparte tiene una atributo del mismo protected, esto es para obtener todos los metodos del mismo y a su vez guardar una copia del objeto componente.
ConcreteDecoratora: Extiende de la clase decorador y tiene los cambios necesarios que impactan en el componente.

Nombre del patrón
Este patrón se lo suele llamar como decorator, decorador o wrapper.

Clasificación del patrón:
Estructural

Intención:
La intención principal de esta patrón es mantener lo que funciona cerrado, sin que lo estemos modificando, si no, que lo tomemos como base.
Proporcionar una forma flexible de introducir o eliminar funcionalidad de un componente sin modificar su apariencia externa o su función.

Motivación:
A veces se desea adicionar responsabilidades a un objeto pero no a toda la clase. Las responsabilidades se pueden adicionar por medio de los mecanismos de Herencia, pero este mecanismo no es flexible porque la responsabilidad es adicionada estéticamente. La solución flexible es la de rodear el objeto con otro objeto que es el que adiciona la nueva responsabilidad. Este nuevo objeto es el Decorator.

Patron Decorator/Decorador - ¿Que es el Patrón de Diseño Decorator?



Ejemplo
Problema: Se quiere diseñar un juego el cual cuenta con 2 tipos de guerreros: el de infantería y el arquero. Cada uno de los guerreros tienen su arma inicial con su correspondiente daño. Caso de infantería espada daño 10, caso de arquero arco daño 5.
A su vez cada uno de los guerreros puede poseer armas de diferentes materiales, los cuales otorgan diferente daño, madera 5, hierro 10, fuego 30, las mismas se pueden combinar.

Solución:
Bueno lo de arriba nos dice básicamente es que vamos tener guerrero de infantería con espada de madera, otro guerrero de infantería con espada de madera y fuego y así obligándonos a tener muchas clases por cada tipo de combinación.
Bueno la solución es sencilla tenemos que separar los "bases" de los "agregados", es decir los principales y los podrían ir combinando o no. Entre los base podemos encontrar los tipos de guerreros ya sea el de infantería y el arquero, luego tenemos que separar los agregados que serian el tipo de material la madera, el fuego y el hierro.

Patrones de  Diseño -  ¿Que es el Patrón de Diseño Decorator?

Código fuente:

GuerroAbstracto
package ar.com.patronesdisenio.decorator.guerrero.base;

/**
* <p>Clase abstracta base para los guerreros</p>
* @author nconde
*/
public abstract class GuerroAbstracto {

public abstract int getDaño();
public abstract String getArmas();
}



Infantería
package ar.com.patronesdisenio.decorator.guerrero;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

/**
* <p>Guerrero de infanteria con los métodos ya implementados</p>
* @author nconde
*/
public class Infanteria extends GuerroAbstracto{

@Override
public int getDaño() {
return 10;
}

@Override
public String getArmas() {
return "Espada";
}
}



Arquero
package ar.com.patronesdisenio.decorator.guerrero;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

/**
* <p>Guerrero de Aruqeria con los metodos ya implementados</p>
* @author nconde
*/
public class Arquero extends GuerroAbstracto{

@Override
public int getDaño() {
return 5;
}

@Override
public String getArmas() {
return "Arco";
}
}


ArmasAbstracto
package ar.com.patronesdisenio.decorator.guerrero.armas.base;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

public abstract class ArmasAbstracto extends GuerroAbstracto{
protected GuerroAbstracto guerrero;
}



Madera
package ar.com.patronesdisenio.decorator.guerrero.armas;
import ar.com.patronesdisenio.decorator.guerrero.armas.base.ArmasAbstracto;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;
/**
* <p>Atributos de un arma de Madera</p>
* @author nconde
*/
public class Madera extends ArmasAbstracto {

public Madera (GuerroAbstracto guerro){
this.guerrero = guerro;
}

@Override
public int getDaño() {
return this.guerrero.getDaño() + 5;
}

@Override
public String getArmas() {
return this.guerrero.getArmas() + " de Madera";
}
}



Hierro
package ar.com.patronesdisenio.decorator.guerrero.armas;
import ar.com.patronesdisenio.decorator.guerrero.armas.base.ArmasAbstracto;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

/**
* <p>Atributos de un arma de Hierro</p>
* @author nconde
*/
public class Hierro extends ArmasAbstracto {

public Hierro (GuerroAbstracto guerro){
this.guerrero = guerro;
}

@Override
public int getDaño() {
return this.guerrero.getDaño() + 10;
}

@Override
public String getArmas() {
return this.guerrero.getArmas() + " de Hierro";
}
}



Fuego
package ar.com.patronesdisenio.decorator.guerrero.armas;
import ar.com.patronesdisenio.decorator.guerrero.armas.base.ArmasAbstracto;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

/**
* <p>Atributos de un arma de Fuego</p>
* @author nconde
*/
public class Fuego extends ArmasAbstracto {

public Fuego (GuerroAbstracto guerro){
this.guerrero = guerro;
}

@Override
public int getDaño() {
return this.guerrero.getDaño() + 30;
}

@Override
public String getArmas() {
return this.guerrero.getArmas() + " con Fuego";
}
}



Main
package ar.com.patronesdisenio.decorator.main;
import ar.com.patronesdisenio.decorator.guerrero.Infanteria;
import ar.com.patronesdisenio.decorator.guerrero.armas.Fuego;
import ar.com.patronesdisenio.decorator.guerrero.armas.Madera;
import ar.com.patronesdisenio.decorator.guerrero.base.GuerroAbstracto;

public class Main {

/**
* @param args
*/
public static void main(String[] args) {

GuerroAbstracto infanteria = new Infanteria();
infanteria = new Madera(infanteria);
infanteria = new Fuego (infanteria);

System.out.println(infanteria.getArmas());
System.out.println(infanteria.getDaño());
}

}


Patrones de Diseño - Patron Decorator/Decorador - ¿Que es el Patrón de Diseño Decorator? Patrones de  Diseño -  Patron Decorator/Decorador - ¿Que es el Patrón de Diseño Decorator? Reviewed by El lado oscuro de java on octubre 08, 2014 Rating: 5

No hay comentarios:

Con la tecnología de Blogger.