sábado, 23 de abril de 2016

Patrones de Diseño Estructurales Parte 3


11. Flyweight: Permite gestionar eficientemente un gran números de objetos pequeños compartiendo objetos más generales. Comparte el apoyo a un gran número de objetos de grano fino de manera eficiente. El patrón flyweight describe como almacenar un gran número de objetos sin un gran costo.
Para conseguir esto se utlizan objetos que almacenan los estados compartidos y que pueden ser usados por varios objetos simultáneamente. Un flyweight es un objeto compartido que se puede utilizar en varios contextos al mismo tiempo. El flyweight actúa como un objeto independiente en cada contexto. Es indistinguible para una instancia del objeto que no es compartida. Flyweight no puede hacer suposiciones sobre el contexto en el que lo operan. El concepto clave aquí se distinguen entre estado intrínseco y extrínseco. El estado intrínseco es almacenado en flyweight; y consiste en información que es independiente del contexto de flyweight; haciendo esto compatible. El estado extrínseco depende y varía con el contexto de flyweight, y por tanto no puede ser compartido. Los objetos del cliente son responsables del paso a estado extrínseco de flyweight cuando este lo necesita. La eficacia del patrón Flyweight depende en gran medida de cómo y dónde se utiliza. Aplicamos el patrón Flyweight cuando una aplicación usa un gran número de objetos, los costos de almacenamiento son altos debido al gran número de objetos, la mayoria de objetos pueden hacerse en estado extrínseco, muchos grupos de objetos se puede sustituir por un número reducido de objetos compartidos, una vez que se elimina el estado extrínseco, la aplicación no depende de la identidad de los objetos.

Diagrama UML

Ejemplo

Un programa que  obtiene el círculo de color deseado que se necesita aplicando este patrón.

Crea una interface
public interface Shape {
   void draw();
}
 Crear clases implentado las mismas interfaces.

public class Circle implements Shape {
   private String color;
   private int x;
   private int y;
   private int radius;

   public Circle(String color){
      this.color = color;      
   }

   public void setX(int x) {
      this.x = x;
   }

   public void setY(int y) {
      this.y = y;
   }

   public void setRadius(int radius) {
      this.radius = radius;
   }

   @Override
   public void draw() {
      System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + 
       ", y :" + y + ", radius :" + radius);
   }
}
Crear los factores  a generar objetos de clases concretas basado en información dada.

import java.util.HashMap;

public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap();

   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

Usa los factores a obtener objetos de clases concretas para pasar información  tal como color.

public class FlyweightPatternDemo {
   private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" };
   public static void main(String[] args) {

      for(int i=0; i < 20; ++i) {
         Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
         circle.setX(getRandomX());
         circle.setY(getRandomY());
         circle.setRadius(100);
         circle.draw();
      }
   }
   private static String getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
   private static int getRandomX() {
      return (int)(Math.random()*100 );
   }
   private static int getRandomY() {
      return (int)(Math.random()*100);
   }
}

11. Proxy: Juega como un intermediario que permite la creación y acceso de un objeto a otros, es decir me sirve como un puente entre objetos, su aplicación más común es el uso de proxies en internet para acceder a páginas o para limitar el tráfico a las mismas. Provee un sustituto de un objeto para controlar el acceso a un objeto. Controlar el acceso a un objeto, puede tener muchas razones, como hacer carga de objetos por demanda para postergar la carga completa del mismo hasta que sea totalmente necesario, por lo general se hace esto cuando final demandado es bastante pesado(por ejemplo imágenes de gran tamaño), otra razón es la protección del objeto, de modo que se pueden hacer validaciones u operaciones necesarias antes de usar el método real del objeto final. Este patrón se usa simpre que se quiera usar como un intermediario para manejar adecuadamente el objeto final, algunas situaciones en las cuales debe aplicarse este patrón cuando es proxy remoto es donde se desea representar un objeto remoto como local, por ejemplo en el uso de librerías externas y en web services, proxy virtual es donde se desea crear objetos pesados por demanda, por ejemplo en la carga de imágenes y  el proxy protector donde se desea controlar el acceso a un objeto, por ejemplo en un login o registro de usuario para filtrar los datos que se envía y quitar cualquier inyección sql u  algunas otra porción de código malicioso o también para la implementación de un ACL entra el cliente y la clase final requerida. El uso de proxies dinámicos permite la ejecución de tareas avanzadas en frameworks de gran coomplejidad como Hibernate o Spring AOP.

Diagrama UML


Ejemplo

En Java es fácil crear proxies dinámicos en tiempo de ejecución a partir de la clase java.lang.reflect.Proxy.
Creamos una interfaz

package com.roldan.proxy;

public interface Lector {
 public void leer();
}
 Ahora creamos una implementación para esta interfaz:
package com.roldan.proxy;

public class LectorImpl implements Lector {

 public void leer(){
  System.out.println("Estamos leyendo...");
 }
}
En este momento, creamos el proxy para la clase LectorImpl:

package com.roldan.proxy;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class LectorProxy
 implements java.lang.reflect.InvocationHandler {

 private Object obj;
 
 public static Object newInstance(Object obj) {
  return java.lang.reflect.Proxy.newProxyInstance(
   obj.getClass().getClassLoader(),
   obj.getClass().getInterfaces(),
   new LectorProxy(obj));
 }

 private LectorProxy(Object obj) {
  this.obj = obj;
 }

 public Object invoke(
  Object proxy,
  Method m,
  Object[] args) throws Throwable {
  Object result;
  try {
   System.out.println(
    "Antes de llamar al metodo " + m.getName());
   result = m.invoke(obj, args);
  } catch (InvocationTargetException e) {
   throw e.getTargetException();
  } catch (Exception e) {
   throw new RuntimeException(e.getMessage());
  } finally {
   System.out.println(
    "Despues de llamar al metodo " + m.getName());
  }
  return result;
 }
}

 Ahora podemos crear una instancia de este proxy y acceder a los métodos de la interfaz Lector que implementa:

package com.roldan.proxy;

public class PruebaLector {
 public static void main(String[] args) {
  Lector lector = (Lector)LectorProxy.newInstance(
   new LectorImpl());
  lector.leer();
 }
}

jueves, 21 de abril de 2016

Patrones de Diseño Estructurales Parte 2

9. Decorator:  Este patrón está hecho para decorar una clase base, es como una envoltura que podemos colocar sobre una clase y que le agrega funcionalidad a esta, estas envolturas las podemos poner en el orden que queramos, combinarlas, ponerlas mas de una vez e incusive quitarlas. Responde a la necesidad de agregar funcionalidad a un objeto por medio de la asociación de clases. Es un objeto con el que se puede ejecutar funcionalidades de varias clases a la vez. Esto nos permite no tener que crear sucesivas clases que hereden de la primera incorporando la nueva funcionalidad, sino otras que la implementan y se asocian a la primera. El patrón Decorator responde a la necesidad de añadir dinámicamente funcionalidad a un Objeto. Esto nos permite no tener que crear sucesivas clases que hereden de la primera incorporando la nueva funcionalidad, si no otras que la implementan y se asocian a la primera.

Diagrama UML.
Crea una interface

public interface Shape {
   void draw();
}

Crea clases concreta implementando las misma interface.

public class Rectangle implements Shape {
 @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Circle");
   }
}


Crear clases abstracta decorator implementando la interface Shape


public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;

   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }

   public void draw(){
      decoratedShape.draw();
   }   
}

Crear clases concreta decorator extendiendo la clase ShapeDecorator.

public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);       
   }

   @Override
   public void draw() {
      decoratedShape.draw();          
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

Usar el RedShapeDecorator a decorar objetos Shape.

public class DecoratorPatternDemo {
   public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}

10. Facade: Se encarga de proveernos de una interfaz más sencilla, para trabajar sólo con ella, y ello nos evita tener que instanciar objetos de un conjunto de clases para sólo aprovechar algunos métodos de tales clases. Facade por lo general requiere de una unica instancia, por ello suele aplicarse el patrón  singleton sobre la fachada, o bien sus métodos como estáticos(de clase). Se aplicará el patrón fachada cuando se necesite proporcionar una interfaz simple para un subsistema complejo, o cuando se quiera estructurar varios subsistemas en capas, ya que las fachadas serían el punto de entrada a cada nivel. Su objetivo principal es proporcionar una interfaz simplificada para un grupo  de subsistemas o un sistema complejo.

Diagrama UML
Ejemplo
Problema un cliente necesita conectarse a una impresora pero desconoce el nombre del impreso y la configuración de la misma solo sabe el texto que la envía a la misma que se debe imprimir, el cliente (como todo cliente/usuario) al meter manos en este dispositivo puede ocasionar problemas graves.
 Impresora

package ar.com.patronesdisenio.facade.impresora;
/**
 * @author nconde
 */
public class Impresora {

 private String nombre;
 private String tipoHoja;
 private String texto;

 public String getNombre() {
  return nombre;
 }
 public void setNombre(String nombre) {
  this.nombre = nombre;
 }
 public String getTipoHoja() {
  return tipoHoja;
 }
 public void setTipoHoja(String tipoHoja) {
  this.tipoHoja = tipoHoja;
 }
 public String getTexto() {
  return texto;
 }
 public void setTexto(String texto) {
  this.texto = texto;
 }
}


FacadeCentral:

  1. package ar.com.patronesdisenio.facade.central;

    import ar.com.patronesdisenio.facade.impresora.Impresora;

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

     private Impresora impresora;

     public void imprimir(String texto){
      impresora = new  Impresora();
      impresora.setNombre("NICO-Printer");
      impresora.setTipoHoja("A4");
      impresora.setTexto(texto);
     }

    }

 ClientMain:

  1. package ar.com.patronesdisenio.facade.cliente;
    import ar.com.patronesdisenio.facade.central.FacadeCentral;

    public class ClienteMain {

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

      FacadeCentral facadeCentral  = new FacadeCentral();
                    facadeCentral.imprimir("Texto a imprimir");
     }

    }

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());

     }
    }

domingo, 17 de abril de 2016

Patron de Arquitectura MVC

Introducción

Siempre al programar los distintos lenguajes de programación simpre afrontamos problemas para realizar los software que se  presenta, ya sea en proyecto o un software comercial, para eso necesitamos una solución a  ello que es un patrón de arquitectura.

En este caso los patrones de arquitectura representa una solución al diseño de software en  este artículo se explicará uno de los patrones de arquitectura que más se conocen pero que a veces no se utiliza por que no hay mucho conocimiento con respecto al tema a la hora de desarrollar el software y este patrón de arquitectura  es el Modelo-Vista-Controlador(por sus siglas MVC).

El patrón MVC puede tener sus ventajas  al utilizarlo y primeramente tener una estructura para desarrollar el software deseado, para este necesitamos conocer los conceptos que lo integran.

Se hará un explicación de los conceptos básicos de este patrón de arquitectura, así como sus características principales. Se explicará a detalle el concepto,  así como una explicación de los elementos que  lo integra.

Además se presentará una ilustracion de como utilizar  este patrón de arquitectura en el lenguaje de progrmación Java, para poder tener una referencia mas clara de este patrón.

El tema que se tratará es para que cuando haya un problema en el desarrollo de software tenga un enfoque para darle una solución a través de este patrón de arquitecctura.

Orígenes del patrón MVC(Modelo-Vista-Controlador)

Es posible afirmar que el patrón MVC(Modelo-Vista-Controlador) fue descrito por primera vez en 1979 por TrygveReenskaug e introducido como parte de la versión Smalltalk-80 de lenguaje de programación SmallTalk.

Fue diseñado para reducir el esfuerzo de programación necesario en la implementación de sistemas múltiples y sincronizados de los mismos datos. Sus características principales están dada por el hecho de que, el Modelo, las Vistas y los Controladores se tratan como entidades separadas; esto hace que cualquier cambio producido en el Modelo se refleje automáticamente en cada una de las Vistas. Este modelo de arquitectura se puede emplear en sistemas de representación gráfca de datos, donde se presentan partes del diseño con diferente escala de aumento, en ventanas separadas.

Concepto del MVC

MVC es un patrón de diseño de arquitectura de software usado principalmente en aplicaciones que manejan gran cantidad de datos y transacciones complejas donde se requiere una mejor separación de conceptos para que el desarrollo esté estructurado de una mejor manera, facilitando la programación de manera paralela e independiente.

Este patrón de arquitectura separa los datos y la aplicación de la interfaz de usuario y el módulo encargado de gestionar los eventos y las comunicaciones.

Ventajas  y Desvantajas del MVC

Este modelo de arquitectura presenta varias ventajas:
  • Separación clara entre los componentes de un programa; lo cual permite su implementación por separado.
  • Interfaz de Programación de Aplicaciones API(ApplicationProgramming Interface) muy bien definida; cualquiera que use el API, podrá reemplazar el Modelo, la Vista o el Controlador, sin aparente dificultad.
  • Conexión entre el Modelo y sus Vistas dinámica; se produce en tiempo de ejecución, no en tiempo de compilación.

Al incorporar el modelo de arquitectura MVC a un diseño, las piezas de un programa se pueden construir por separado y luego unirlas en tiempo de ejecución. Si uno de los componentes, posteriormente, se observa que funciona mal, puede reemplazarse sin que las otras piezas se vean afectadas. Esta escenarios contrasta con la aproximación monolítica típica de muchos programas de pequeña y mediana complejidad. Todos tienen un Frame que contiene todos los elementos, un controlador de eventos, un montón de cálculos y la presentación del resultado. Ante esta perspectiva, hacer un cambio aquí no es nada trivial.

 Este módelo también presenta desvantajas como:
  • La separación de conceptos en capas agrega complejidad al sistema.
  • La cantidad de archivos a mantener y desarrollar se incrementa considerablemente.
  • La curva de aprendizaje del patrón de diseño es más alta que usando otros modelos mas sencillo.
Elementos del MVC

Modelo: Es la capa que trabaja con los datos. Deberá contener mecanismos para acceder a la información y también para actualizar su estado. Es decir, gestionar todos los accesos a esa información, consultas tanto para informes como de mantenimiento(actualización), valorar los privilegios de acceso que habrán sido descritos en las especificaciones de la aplicación que llamamos lógica de negocio. Como resultado envía  a "vista" aquella parte de la información que se le solicita para ser mostrada. Se debe tener en cuenta que las peticiones de acceso y/o manipulación  de los datos o información llega a "modelo" o a través de "controlador".

Es responsable de:
  • Acceder a la capa de almacenamiento de datos. Lo ideal es que el modelo se independiente del sistema de almacenamiento.
  • Define reglas de negocios (la funcionalidad del sistema). Un ejemplo puede ser: "Si la mercancia pedida no está en el almacen, consultar el tiempo de entrega en el proveedor". Es opcional, pues la regla de negocio, puede estar también en controladores, directamente en ñas acciones.
  • Notificará a las vistas los cambios que en los datos puedan producir un agente externo si se está ante un modelo activo(por ejemplo, un fichero bath que actualiza los datos, un temporizador que desencadena una inserción, etc.) 

Vista: Es la representación del modelo en forma gráfica disponible para la interacción con el usuario. En el caso de una aplicación Web, la "Vista" es una página HTML con contenido dinámico sobre el cual el usuario puede realizar operaciones.

Es responsable de:
  • Recibir datos procesados por el controlador o del modelo y mostrarlos al usuario.
  • Tiene un registro de su controlador asociado.
  • Pueden dar el servicio de "Actualización()", para que se invocado por el controlador o por el modelo cuando es un modelo activo que informa de los cambios en los datos producidos por otros agentes.

Controlador: Es la parte mediante la cual se maneja la ordenes de usuario, y  a través del cual podemos acceder a cambiar el estado de la aplicación correspondiente. A diferencia de la vista, el controlador reacciona sobre la base de las acciones que realice el usuario en la vista. Es la encargada de manejar y responder la información necesaria y modificando el Modelo en caso de ser necesario.

Es responsable de:
  •  Recibir los eventos de entradas(un click, un cambio en un campo de texto, etc.).
  • Contiene la reglas de gestión de eventos, del tipo "Si Evento Z Accion W". Estas acciones pueden suponer peticiones al modelo o  a las vistas. Una de estas peticiones a las vistas puede ser una llamada al método "Actualizar ()". Una petición del modelo puede ser "Obtener_tiempo_ de_entrega (nueva orden de venta)".

Cada uno de los elementos llamdos capas interrelaciona entre si como se muestra en el siguiente diagrama:

 










Ciclo de vida MVC

El ciclo de vida MVC es normalmente representado por las 3 elementos o capas presentadas anteriormente y el cliente (también conocido como el usuario). El siguiente diagrama representa el ciclo de vida de manera sencilla:




El primer paso en el ciclo de vida empieza cuando el usuario hace una solicitud al contorolador con información sobre lo que el usuario desea realizar. Entonces el Controlador decide a quién debe delegar la tarea y es aquí donde el Modelo empieza su trabajo. En esta etapa, el Modelo se encarga de realizar operaciones sobre la información que maneja para cumplir con lo que solicita el Controlador. Una vez que termina su labor, le regresa al controlador la información de sus operaciones, el cual a su vez redirige a la Vista. La Vista se encarga de transformar los datos en información visualmente entendible para el usuario. Finalmente, la representación gráfica es transmitida de regreso al Controlador y éste se encarga de transmitírsela al usuario. El ciclo entero puede empezar nuevamente si el usuario así lo requiere.

MVC en Uso

Actualmente existen muchos frameworks disponibles para el desarrollo de aplicaciones MVC; sin embargo su uso requiere de una comprensión completa de su funcionamiento.

Para desarrollar aplicaciones Java para internet es necesario hacer uso de la tecnología Java Server Pages, las cuales permiten incrustar código que generen paginas con contenido dinámico cuando cualquier cliente Web solicite información del servidor.

Los  JSPs pueden ser entendidos como una abstracción de alto nivel de un Servlet ya que puede ser entendidas por el servidor Web es necesario que sean compiladas en forma de un Servlet y posteriormente sean interpretadas por un compilador de Java.

Con el proposito de seguir el patrón MVC , como ejemplo, se usa la tecnología Java Servlets para cumplir las funciones del Controlador, la tecnología JSP para las funciones de las vistas e los Benas para el Modelo.

 

 

Conclusión

Los patrones de arquitectura son útiles para desarrollar software ya sea en el área web, aplicaciones de esscriorios y últimamente aplicaciones móviles.

La evolución de los patrones de arquitecturas tiene una largo camino por recorrer  para desarrollar software más eficiente y estructuras mas complejas pero a la vez más simples de enteneder para el desarollador y para el cliente que incluya menos costos.

Por lo pronto el patrón que se explicó en este articula, cumple con gran parte de flexibilidad, portabilidad y eficiencia en el desarrollo de software, pero aún falta por evolucionar y afinar detalles que cumplan con el proceso de desarrollo de software deseado.

También faltaría que en la gran diversidad de tecnologías se adapte o se ajuste de una manera eficiente al patrón de arquitectura, obviamente nadie tiene la verdad absoluta los demás patrones de arquitecturas tiene sus ventajas y se adapta según  a la necesidad del cliente y del equipo de desarrollo de software.

Se ha conocido todo sus elementos y como  interactúan cada uno de ellos en el patrón de arquitectura MVC para una mejor comprensión.

Bibliografía

  • Yanisleidy Fernández Romero, Yanette Díaz González Revista Telemática Págs. 47-50  Abril 2012.
  • http://catarina.udlap.mx/u_dl_a/tales/documentos/lis/rivera_l_a/capitulo2.pdf
  •  Jose Talledo San Miguel, Implantación de aplicaciones web en entornos internet, intranet y extranet Pág. 174 2015.
  • Francisco Juan Mouzo Lerma, Mariano Makendonsky Flash Desarrollo Profesional Pag. 115 2011.


Reflexión

¿Porque has elegido ese tema? ¿De donde partiste para empezar a escribir?

Para contestar la primera pregunta es porque me interesa el desarrollo de software y me interesa concocer la estructura de como a través de buenas metodologías se puede desarrollar software eficiente y menos costoso además  de como conocer la programación en capas y las diferentes tecnologías en las cuales se puede ajustar distintos proyectos para la aplicación de software de tipo comercial, y me interesó por que ya tenía una estructura  bien definida es un tema interesante y conocer los elementos  y su interacción.

Me gustó bastante definir este tema por que concoces todo lo relacionado a la arquitectura de software y es un  amplío aprendizaje que incluso ha llevado varias tesis, incluso la aplicación del mismo.

Parti para empezar este tema desde el concepto para poder escribir este artículo  y empezar a describir cada uno de estos puntos y a través de un árbol desmenuzar cada elemento que compone el tema.

viernes, 15 de abril de 2016

Patrones de Diseño Creacionales Parte 3

5. Singleton: Se asegura de que sólo exista una instacia de esa clase, si varios objetos utilizan esta instancia, siempre será la misma para cualquiera de ellos. El objetivo de este patrón es que habrá ocasiones en que una clase sólo requiera de una instancia única, algunos dicen que el patrón singleton es la mejora a las variable globales, lo cual así creo. Este patrón regularmente se usa para el manejo de recursos. Estos recursos pueden ser externos como internos, por mencionar un ejemplo de externo sería una clase que maneje el uso de conexiones a base de datos. Mientras que uno interno sería llevar el control de algunos eventos que ocurren durante la ejecución del programa los cuales podrían ser errores, estadísticas, etc. Como podemos ver en el diagrama de clase de clase.
Diagrama UML
Ejemplo
El ejemplo del patrón realiza una conexión a base de datos mysql para hecer un select de un tabla.
Creamos la clase ConnectDB que utilizaremos para crear el patrón.

  1. package com.elkardumen.conexion;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;

    public class ConnectDB {

     private static Connection connect;
     private static ConnectDB instance;

     private ConnectDB() {

     try {

    Class.forName("com.mysql.jdbc.Driver");
     // connect DB
     connect = DriverManager.getConnection("jdbc:mysql://127.0.0.1/MyDataBase","root", "");
    }

     catch (SQLException e) {
    System.err.println(e.getMessage());

    }

     catch (ClassNotFoundException e) {
    System.err.println(e.getMessage());
    }
    }

     public static ConnectDB getInstance() {
     //Esto servira para que solo se haga una vez garantizando el patron singleton
     if (instance == null) {
  2. System.out.println("Se crea la instancia solo una vez garantizanco el patron Singleton");
     instance = new ConnectDB();
    }

     return instance;

    }

     public static Connection getConnect() {
     return connect;
    }

     public static void setConnect(Connection connect) {
    ConnectDB.connect = connect;
    }


Creamos la clasePrincipal con el siguiente código:

  1. package com.elkardumen;

    import java.sql.ResultSet;
    import java.sql.Statement;

    import com.elkardumen.conexion.ConnectDB;

    public class Principal {

     /**
    * @param args
    */
     public static void main(String[] args) {
     try{
     //Creamos El primer llamado
    ConnectDB con = ConnectDB.getInstance();
    Statement stmt = con.getConnect().createStatement();
    String query = "select * from micatalogo;" ;
    ResultSet rs = stmt.executeQuery(query) ;
     while (rs.next())
    {
    System.out.println (rs.getInt (1) + " - " + rs.getString (2)+ " - " + rs.getString(3));
    }
     //Creamos El segundo llamado
    ConnectDB con2 = ConnectDB.getInstance();
    Statement stmt2 = con2.getConnect().createStatement();
    rs = stmt.executeQuery(query) ;
     while (rs.next())
    {
    System.out.println (rs.getInt (1) + " - " + rs.getString (2)+ " - " + rs.getString(3));
    }
    }catch(Exception e){
    e.printStackTrace();
    }


    }


    }