27 de octubre de 2010

Patrón Singleton

Cuando escribí el artículo Desarrollo en capas, un amigo me comento que de alguna manera debería de explicar que es el patrón Singleton.

Bien su suplica se ha hecho realidad y para ejemplificar utilizaré Java

En realidad este patrón es muy simple. La idea básica de este patrón es que solo pueda existir una instancia de una clase en la aplicación.

El primer paso para conseguir este patrón es bloquear la forma de generar instancias de la clase, esto se hace simplemente privatizando el constructor de la clase


  public class Singleton{

      private Singleton(){}     
 

  }


El punto principal de este patrón esta en los miembros de clase o miembros estáticos, ya que estos se crean mediante el ClassLoader, algo similar a las variables globales en la programación estructurada, lo cual quiere decir que su consentido es persistente por todo el ciclo de vida de la aplicación.

Así que utilizando la potencia de los miembros estáticos crearemos una instancia estática de la clase para que viva durante toda la vida de la aplicación.


public class Singleton {

     private static Singleton singleton = new Singleton();


     private Singleton(){}

}

Ahora solo falta tener alguna forma de acceder a este objeto, y esto es mediante un método estático


public class Singleton {

    private static Singleton singleton
= new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
       return Singleton.
singleton;
    }
}

Cuando utilizar el patrón Singleton

La forma mas utilizada para aplicar este patrón, es para la capa de acceso a datos. Generalmente por cada operación que necesitemos hacer con la base de datos, creamos una nueva conexión, nos autentificamos y en seguida mandamos las sentencias SQL que necesitemos ejecutar.

Si aplicamos un patrón Singleton a la conexión a la base de datos y mantenemos la conexión abierta, nos evitaremos abrir y cerrar la conexión por cada petición

A continuación pongo un pequeño ejemplo de la aplicación de este patrón

Clase ConnectionDao


public class ConnectionDao {

   
private static ConnectionDao connectionDao;
   
private Connection connection;

   
private ConnectionDao() throws ExceptionInInitializerError{
       try {
          String classDriver = "...";
          String url = "...";
          Class.forName(classDriver).newInstance();
          connection = DriverManager.getConnection(url);
       } catch (Exception ex) {
          throw new ExceptionInInitializerError(ex);
       }
    }

    public ResultSet executeQuery(String query) throws SQLException{
       Statement statement = connection.createStatement();
       return statement.executeQuery(query);
    }

    public boolean executeNonQuery(String query) throws SQLException{
       Statement statement = connection.createStatement();
       return statement.execute(query);
    }

    
    public PreparedStatement getPreparedStatement(String query) 
            throws SQLException{
        return connection.prepareStatement(query);
    }

    public static ConnectionDao getInstance(){
       if(ConnectionDao.connectionDao == null)
          ConnectionDao.connectionDao = new ConnectionDao();
       return ConnectionDao.connectionDao;
    }




El constructor se encarga de establecer la conexión a la base de datos, pero esta no se cierra para dejar el canal de comunicación siempre abierto.

El método estático getInstance() es el encargado de crear la instancia de la clase ConnectionDao si esta no existe y de regresar una referencia a dicha instancia


Clase UsuarioDao


public class UsuarioDao {

    public void insertar(String... datos){
   
    try {
            String sql = "insert ...";
            ConnectionDao.getInstance().executeNonQuery(sql);
        } catch (SQLException ex) {
            ...
        }
    }

    public void buscar(String... datos){
        try {
            String sql = "select ...";
            ConnectionDao connection = ConnectionDao.getInstance();
            connection.executeQuery(sql);
        } catch (SQLException ex) { 
            ...
        }
    }

    public void actualizar(String... datos){
        try {
            String sql = "update ...";
            ConnectionDao connection = ConnectionDao.getInstance();
            PreparedStatement prepared =   
                connection.getPreparedStatement(sql);
            prepared.setString(1,datos)
            prepared.executeUpdate();
        } catch (SQLException ex) {             
           ...
        }
    }
}

Así para obtener la referencia al objeto ConectionDao llamamos al método ConnectionDao.getInstance(); que nos dará acceso a los metodos " executeQuery", " executeNonQuery " y "getPreparedStatement"

De esta manera concluye este pequeño tutorial sobre el patrón Singleton, si tienen alguna duda o un comentario, no duden en dejarlo e intentaré atenderlo lo mas pronto posible

Un Saludo

3 comentarios:

  1. Qué hay Hugo.

    Me falta leer con un poco más de detenimiento tu nueva aportación, pero de entrada está muy bien.

    Por otro lado, en cuanto a la parte del diseño del blog y a mi manera de ver, deberías asegurarte que sólo una porción de cada publicación salga en la página principal, con el objetivo de facilitar la legibilidad de la misma.

    Saludos y excelente esfuerzo.

    ResponderEliminar
  2. Saludos!

    En que momento es recomendable cerrar la conexion?

    ResponderEliminar