Páginas

7 sept. 2012

GRASP: Polimorfismo

A lo largo de todos los artículos que llevo escritos en éste blog ha aparecido la palabra polimorfismo más de una decena de veces, seguro, y he dado por hecho que todo el mundo sabía de qué estaba hablando, pero ¿Qué es polimorfismo?

Polimorfismo, en programación orientada a objetos, es un concepto muy simple con el que la gente a veces se lía, polimorfismo es permitir que varias clases se comporten de manera distinta dependiendo del tipo que sean. 

Siempre que se tenga que llevar a cabo una responsabilidad que dependa de un tipo, se tiene que
hacer uso del polimorfismo, es decir, asignaremos el mismo nombre a servicios implementados en 
diferentes objetos acordes con cada tipo.

Como de costumbre, veamos ésto con un ejemplo "malo", es decir, mejorable, la explicación y un ejemplo que lo soluciona.

Mal:
public enum TipoDeLog
{
    Debug,
    Error
}

public class Log
{
    StreamWriter _ficheroLog;

    public void Registrar(string mensaje, TipoDeLog tipoDeLog)
    {
        switch (tipoDeLog)
        {
            case TipoDeLog.Debug:
                _ficheroLog.WriteLine("[DEBUG];{0}", mensaje);
                break;
            case TipoDeLog.Error:
                _ficheroLog.WriteLine("[ERROR]:{0}", mensaje);
                break;
        }
    }
}

public class CualquierPresentador
{
    Log _log;
    public void AlgoHaSucedido()
    {
        _log.Registrar("Algo ha sucedido y queremos dejar constancia en un registro.", TipoDeLog.Debug);
    }
}
¿Por qué?

Se ve claramente la dependencia de la clase Log y el método registrar con el TipoDeLog. Podemos evitar ésto creando una interfaz para el mensaje implementada de dos formas distintas, una por cada tipo, y sólo tendremos que pedir a la clase Log que registre un IMensaje. Y dependiendo de qué mensaje queramos registrar, quien sepa de qué tipo debe ser registrado, es decir, el experto en información, que cree una instancia concreta y llame a Log.Registrar.

Bien:
public interface IMensajeDelLog
{
    string Valor { get; }
}

public class MensajeDebug : IMensajeDelLog
{
    readonly string _mensaje;

    public MensajeDebug(string mensaje)
    {
        _mensaje = mensaje;
    }

    public string Valor
    {
        get
        {
            return string.Format("[DEBUG];{0}", _mensaje);
        }
    }
}

public class MensajeError : IMensajeDelLog
{
    readonly string _mensaje;

    public MensajeError(string mensaje)
    {
        _mensaje = mensaje;
    }

    public string Valor
    {
        get
        {
            return string.Format("[ERROR];{0}", _mensaje);
        }
    }
}

public class Log
{
    StreamWriter _ficheroLog;

    public void Registrar(IMensajeDelLog message)
    {
        _ficheroLog.WriteLine(message.Valor);
    }
}

public class CualquierPresentador
{
    Log _log;

    public void AlgoHaSucedidoYQueremosRegistrarUnError()
    {
        _log.Registrar(new MensajeError("Algo ha sucedido y queremos dejar constancia en un registro."));
    }

    public void AlgoHaSucedidoYQueremosRegistrarloParaDepurar()
    {// Por ejemplo una excepción
        _log.Registrar(new MensajeDebug("Algo ha sucedido y queremos dejar constancia en un registro."));
    }
}

Como vemos, aplicar polimorfismo nos lleva a aplicar otros principios y mejora la calidad de nuestro código. Que nunca falte una buena cantidad de polimorfismo en vuestros programas.

Juan García Carmona

1 comentario:

  1. Hola Juan.
    Estoy estudiando la asignatura de Diseño del Software en el Grado en Ingeniería Informática de Sistemas por la UNED y estaba teniendo dificultad para entender este patrón.

    Gracias a tu explicación, ahora lo tengo más claro y además he comprendido perfectamente cual es su ventaja.

    Un saludo.

    ResponderEliminar