martes, 19 de abril de 2016

Patrones de Diseño Estructurales Parte 1


6. Adapter o Wrapper: Esta patrón convierte la interfaz de una clase en otra distinta que es la que esperan los clientes  y permite que cooperan clases que de otra manera no podrían por tener interfaces incompatibles. Se encarga de proporcionar a una clase cliente el interfaz que necesita para trabajar utilizando en su implementación una clase o clases que no cumplen con dicho interfaz. Como su propio nombre lo indica, éste patrón se encarga de adaptar clases de interfaz incompatible para que trabajen de manera conjunta. Establece una capa intermedia que permita comunicarse a dos clases que de otro modo no podrían hacerlo, realizando una adaptación de la interfaz de la clase que proporciona el servicio a la que la solicita.

Diagrama UML

Ejemplo

Problema: Actualmente se tiene un auto, el mismo puede tener 3 tipos de motores diferentes: Naftero, Diesel, y a GNC (Gas Natural Comprimido), pero este último el GNC no posee los métodos de prender y apagar, sino de calentar y parar. Se requiere que el auto pueda utilizar cualquiera de estos motores indiferentemente.

Motor
 
  1. package ar.com.patronesdisenio.adapter.abs;
    /**
     * @author nconde
     */
    public abstract class Motor {

     public abstract void encender();
     public abstract void apagar();
    }

Motor Diesel
 
  1. package ar.com.patronesdisenio.adapter.imp;
    import ar.com.patronesdisenio.adapter.abs.Motor;
    /**
     * @author nconde
     */
    public class MotorDiesel extends Motor {

     @Override
     public void encender() {
       System.out.println("Encender motor Diesel");
     }

     @Override
     public void apagar() {
      System.out.println("Apagar motor Diesel");
     }

    }

MotorGNC
 
  1. package ar.com.patronesdisenio.adapter.imp;

    /**
     * @author nconde
     */
    public class MotorGNC {

     public void calentar(){
      System.out.println("Calentando el motor GNC");
     }
     public void parar(){
      System.out.println("Parando el motor GNC");
     }

    }


MotorNaftero
 
  1. package ar.com.patronesdisenio.adapter.imp;
    import ar.com.patronesdisenio.adapter.abs.Motor;
    /**
     * @author nconde
     */
    public class MotorNaftero extends Motor {

     @Override
     public void encender() {
       System.out.println("Encender motor Naftero");
     }

     @Override
     public void apagar() {
      System.out.println("Apagar motor Naftero");
     }

    }

 MotorAdaptadorGNC
 
  1. package ar.com.patronesdisenio.adapter.imp;
    import ar.com.patronesdisenio.adapter.abs.Motor;
    /**
     * @author nconde
     */
    public class MotorAdaptadorGNC extends Motor {
     MotorGNC motorGNC;

     public MotorAdaptadorGNC(){
      this.motorGNC = new MotorGNC();
     }
     @Override
     public void encender() {
       System.out.println("Encender motor GNC");
       this.motorGNC.calentar();
     }

     @Override
     public void apagar() {
      System.out.println("Apagar motor GNC");
      this.motorGNC.parar();
     }

    }

Auto
 
  1. package ar.com.patronesdisenio.adapter;
    import ar.com.patronesdisenio.adapter.abs.Motor;
    import ar.com.patronesdisenio.adapter.imp.MotorAdaptadorGNC;
    import ar.com.patronesdisenio.adapter.imp.MotorDiesel;
    import ar.com.patronesdisenio.adapter.imp.MotorNaftero;

    /**
     * @author nconde
     */
    public class Auto {

     /**
      * @param args
      */
     public static void main(String[] args) {
      //Motor Diesel
         Motor motorDiesel = new MotorDiesel();
         motorDiesel.encender();
         motorDiesel.apagar();
        
         //Motor Naftero
         Motor motorNaftero = new MotorNaftero();
         motorNaftero.encender();
         motorNaftero.apagar();
        
         //Motor GNC
         Motor motorAdaptadorGNC= new MotorAdaptadorGNC();
         motorAdaptadorGNC.encender();
         motorAdaptadorGNC.apagar();
     }
    }

 7. Bridge: Permite desacoplar una abstracción de su implementación, de manera que ambas puedan variar de forma independiente. Desacopla  una abstracción de su implementación de manera que ambas puedan variar independientemente, publica la interfaz en una jerarquía de herencias y ocultar la implementación en su propia jerarquía de herencia, además de encapsulación se usa para aislamiento. Esta patrón permite modificar las implementaciones de una abstracción en tiempo de ejecución. Básicamente es una técnica usada en programación para desacoplar la interface de una clase de su implementación, de manera que ambas puedan ser modificadas independientemente sin necesidad de alterar por ello la otra.

Diagrama UML

 Ejemplo

En el siguiento ejemplo, se lleva a cabo la solicitud de un pedido en una panadería, donde el cliente elige el diferente tipo de pan que hay disponible.

Nuestra clase abstracta Panaderia, su método permite obtener el tipo de pan de Pedido.
 
  1. package Logica;
    public abstract class Panaderia {                
          public abstract TipoDePan getImplementador();
          public abstract String nombrePan();
    }

Ahora creamos una clase que hereda de panadería, en la cual se estructura el método de la clase abstracta y se crean nuevos métodos, los cuales trabajan con un objeto de la que implementa la interfaz.

  1. package Logica;
    public class Panes extends Panaderia {
     private TipoDePan pan;

     public String nombrePan() {
      return pan.tipoPan();
     }
     public void setInterfaz(TipoDePan tipoInterfaz) {
      pan = tipoInterfaz; 
     }
     public TipoDePan getImplementador() {
      return pan;
     }
    }

Creamos la interfaz.

  1. package Logica;
    public interface TipoDePan {
     public abstract String  tipoPan();
    }
    }

Ahora se crean las clases de los diferentes tipos de pan disponibles sobreescribiendo el método implementado de la interfaz.

  1. package Logica;
    public class PanDeFrutas implements TipoDePan {
     public String tipoPan() {
      return "Pan de Frutas";
     }
    }

  1. package Logica;
    public class PanIntegral implements TipoDePan {
     public String tipoPan() {
      return "Pan integral";
     }
    }

  1. package Logica;
    public class PanLight implements TipoDePan {
     public String tipoPan() {
      return "Pan Light";
     }
    }

Por últmo tenemos la ventana donde el cliente podrá seleccionar y obtener su pedido.

  1. package Interfaz;
    import Logica.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    public class Pedido extends JFrame implements ActionListener {
    //atributos de la clase//
     Panaderia panaderia ;
     private JButton panIntegral;
     private JButton panLight;
     private JButton panDeFrutas;
     private JLabel suOrden;
     //constructor de la clase, e inicializamos y ubicamos los atributos//
     public Pedido(){
     this.setSize(400,300); 
            this.setLayout(null);
            this.setDefaultCloseOperation(Pedido.DISPOSE_ON_CLOSE);
            this.setTitle(":::Panaderia:::");
                   
     suOrden = new JLabel();
     suOrden.setSize(300,100);
     suOrden.setLocation(30, 20);
     suOrden.setText("Seleccione su Pan :");
            this.getContentPane().add(suOrden);
           
     panIntegral = new JButton();
     panIntegral.setSize(110, 30);
     panIntegral.setLocation(10, 100);
     panIntegral.setText("pan Integral");
            this.getContentPane().add(panIntegral);
            panIntegral.addActionListener(this);
            panLight = new JButton();
            panLight.setSize(110, 30);
            panLight.setLocation(130, 100);
            panLight.setText("pan Light");
            this.getContentPane().add(panLight);
            panLight.addActionListener(this);
            panDeFrutas = new JButton();
            panDeFrutas.setSize(120, 30);
            panDeFrutas.setLocation(250, 100);
            panDeFrutas.setText("pan De Frutas");
            this.getContentPane().add(panDeFrutas);
            panDeFrutas.addActionListener(this);
     }

     //manupula el objeto segun la especificacion del cliente//
     @Override
     public void actionPerformed(ActionEvent e) {
    //inicializa un objeto de la clase Panes//
            Panes pan= new Panes();
      if (e.getSource() == panDeFrutas) {
    //reliza la implemntacion pasando en su método el tipo de pan que se eligió//
       pan.setInterfaz(new PanDeFrutas());
            }
            if (e.getSource() == panLight) {
             pan.setInterfaz(new PanLight());   
            }
            if (e.getSource() == panIntegral) {
             pan.setInterfaz(new PanIntegral());
            }
    //se presenta al cliente el pedido como tal//
            suOrden.setLocation(100, 130);
            suOrden.setText("Su orden es : " + pan.nombrePan());
     }
    }

8. Composite:  Permite construir objetos complejos partiendo de otros más sencillo utilizando una estrategia de compocisión recursiva. Podemos equiparar este patrón a un panel y sus celdas. Cada objeto simple (celda) puede relacionarse con otros formando una estructura más compleja(panel).Lo podemos ver también como un libro cada hoja(objeto sencillo) se puede relacionar con otras hojas y forman un libro(objeto compuesto). Combina objetos en estructuras de árbol para representar jerarquias de parte-todo. Permite que los clientes traten de manera uniforme a los objetos individuales y a los compuestos.

Diagrama UML



Ejemplo

Problema: Actualmente a un escritor  se le solicita escribir diferentes hojas, por cada hoja que escriba recibe un monto diferente y tambien se le solicita escribir un libro, pero se desconoce la cantidad de hojas que posee el libro, pero se requiere en algún momento solicitar el precio, ya sea de la hoja individual o del libro.


AbstractCompositor

  1. package ar.com.patronesdisenio.compositor.base;
    /**
     * @author nconde
     */
    public abstract class AbstractCompositor {

       public abstract int getCosto();
       public abstract void agregarHoja(AbstractCompositor composicion);
    }
  2.  

Hoja

  1. package ar.com.patronesdisenio.compositor.componentes;
    import ar.com.patronesdisenio.compositor.base.AbstractCompositor;

    /**
     * @author nconde
     */
    public class Hoja extends AbstractCompositor {

     private int costo;
     public Hoja(int costo){
      this.costo = costo;
     }

     @Override
     public int getCosto() {
      return this.costo;
     }

     @Override
     public void agregarHoja(AbstractCompositor composicion) {
      // metodo no se usa
     }
    }

Libro

  1. package ar.com.patronesdisenio.compositor.componentes;
    import java.util.ArrayList;
    import java.util.List;
    import ar.com.patronesdisenio.compositor.base.AbstractCompositor;

    /**
     * @author nconde
     */
    public class Libro extends AbstractCompositor {

     private int costo = 0;
     private List<AbstractCompositor> listaComposicion;

     /**
      * Constructor
      */
     public Libro (){
      listaComposicion = new ArrayList<AbstractCompositor>();
     }

     /**
      * Obtiene el costo del libro
      */
     @Override
     public int getCosto() {
      return this.costo;
     }

     /**
      * Agrega las hojas y calcula su valor rapidamente.
      * @param composicion
      */
     public void agregarHoja(AbstractCompositor composicion){
      this.costo = this.costo + composicion.getCosto();
      this.listaComposicion.add(composicion);
     }
    }

Main

  1. package ar.com.patronesdisenio.compositor.main;
    import ar.com.patronesdisenio.compositor.base.AbstractCompositor;
    import ar.com.patronesdisenio.compositor.componentes.Hoja;
    import ar.com.patronesdisenio.compositor.componentes.Libro;

    /**
     * @author nconde
     */
    public class Main {

     /**
      * @param args
      */
     public static void main(String[] args) {
         AbstractCompositor componenteUno = new Hoja(10);

         System.out.println(componenteUno.getCosto());
        
         AbstractCompositor componenteTres = new Hoja(3);
         AbstractCompositor componenteDos = new Libro();
        
         componenteDos.agregarHoja(componenteUno);
         componenteDos.agregarHoja(componenteTres);
        
         System.out.println(componenteDos.getCosto());

     }
    }

No hay comentarios:

Publicar un comentario