Las factorías y el principio de responsabilidad única

COMPARTIR 0 TWITTEAR

SingleResponsibilityPrinciple

Siguiendo nuestro curso de programación hoy no veremos un patrón de diseño nos centraremos en mejorar un código que mezcla la creación de un objeto con las interacciones sobre dicho objeto y como esto, amparándonos en los principios SOLID, en concreto el principio de responsabilidad única, veremos que como no es correcto y que tendremos que realizar una refactorización del código. Esta refactorización dará lugar a Factoría. Tenemos que tener claro que para nosotros, una factoría es cualquier método u objeto que se usa para crear otros objetos. Sin embargo el término factorías se refiere a los patrones de creación Abstract Factory y Factory Method que veremos más adelante.

Ejemplo

Supongamos estamos desarrollando una aplicación para una pizzería en la que tendremos que crear nuestra Pizza pero también prepararlas, cocinarlas, cortarlas… Lo primero que nos viene a la cabeza, siguiendo un modelo de desarrollo orientado a objeto, es crear una clase Pizza con un método que se encarga de crear la Pizza pero también de prepararla.

public Class Pizzeria {
    Pizza orderPizza() {  
       Pizza pizza;
       pizza = new Pizza();

       pizza.prepare();
       pizza.bake();
       pizza.cut();
       pizza.box();
       return pizza;

    }
}

Lo primero que podemos pensar de este diseño es que quizás en la pizzeria se quiera distinguir los distintos tipos de pizza como por ejemplo las cuatro quesos, chorizo, vegetal… Podemos sustituir el método por algo similar a:

Pizza orderPizza(String type) {
    Pizza pizza;

    if (type.equals("cheese")) {
        pizza = new CheesePizza();
    } else if (type.equals("greek")) {
        pizza = new GreekPizza();
    else if (type.equals("pepperoni")) {
        pizza = new PepperoniPizza();
    }

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();
    return pizza;
}

Cuando se pide una pizza, le pasamos el tipo de pizza a crear. ¿Qué ocurre si añadimos nuevos tipos de Pizza o eliminamos alguno? En este caso, parece razonable pensar que la primera parte del método (donde creamos la Pizza) que más propensa es a cambiar con el tiempo (porque se cambia la selección de pizzas) pero también tiene una parte que se espere que no cambie. Tenemos que tener en cuenta que en este diseño, cada tipo de pizza sabe cómo prepararse a sí misma. En muchos casos, en problemas reales, esto no tiene por qué ser necesariamente así.

Tenemos un problema, tenemos que aplicar los principios SOLID en los que nos indican que debemos separar la creación de un objeto con lo que sería la interacción con él. Sacaremos la la lógica de la creación del objeto fuera del método orderPizza a un objeto aparte que llamaremos SimplePizzaFactory. Tenemos que tener siempre claro que una clase debe encargarse de crear y gestionar los objetos o bien utilizarlos (interaccionar), pero nunca ambas cosas. Debe tener poco acoplamiento; división de las tareas. Debe cumplir el principio de responsabilidad única.

uml_inicial_factoryMethod

Tendriamos un código similar a:

public class Pizzeria {
    SimplePizzaFactory factory;

    public PizzaStore(SimplePizzaFactory factory) {
      this.factory = factory;
    }
    public Pizza orderPizza(String type) {
      Pizza pizza;
      pizza = factory.createPizza(type);
      pizza.prepare();
      pizza.bake();
      pizza.cut();
      pizza.box();
      return pizza;
    }
}

Mientras que la clase encargada de crear las pizzas sería:

public class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        if (type.equals("queso")) {
            pizza = new PizzaQueso();
        } else if (type.equals("chorizo")) {
            pizza = new PizzaChorizo();
        } else if (type.equals("vegetal")) {
            pizza = new PizzaVegetal();
        }
        return pizza;
    }
}

Después de todo, el código sigue estando parametrizado por el tipo de pizza, y lo único que hemos hecho ha sido trasladar el problema a otro objeto. Efectivamente, así es y en un ejemplo tan tonto no se aprecia ninguna ventaja (aparte de la legibilidad del código y de que cada método y, a ser posible, cada clase, se dediquen a una sola cosa, que por sí sólo posiblemente ya hiciera que mereciese la pena separarlo). Pero hemos de pensar que muchas veces dicha lógica se repite en distintos puntos del programa. La clave está en eliminar la creación de los objetos concretos de la lógica del cliente, de manera que sólo haya que ir a un sitio cuando las clases concretas cambien.

En próximos artículos veremos como evolucionar este ejemplo hacía algún patrón de diseño de creación. Os animo haber si sois capaces a realizar una refactorización de este código hacía un Abstract Factory o un Factory Method.

Archivado en Curso de Programación, Factorias, Java
COMPARTIR 0 TWITTEAR

Comentarios (5)

Usa tu cuenta de Facebook para dejar tu opinión.

  • josep dice:

    una consulta, yo todavia no comienzo el curso y me descarge eclipce (ya lo prove) y los 28 partes del curso, esto te lo digo porque soy de chiule y hago un viaje en avion que combinado hace mas de 30 horas en avion, ahi quiero comenzarlo. mi pregunta era ¿durante el curso hay que descargar algo adicional?

    • Francisco J. Gil Gala dice:

      Hola. Te recomiendo tener algún libro de cabecera para seguir los ejemplos en la parte introductoria a Java y también es especialmente importante leer el libro GoF o Gamma (http://www.amazon.es/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) (los ejemplos están en C++ pero son facilmente entendible si comprendes Java)

      sobre el libro de Java; en realidad cualquiera te vale; la idea es que contraste la información que aquí resumo.

      Es importante añadir que todavía no se han tocado la parte dedicada a las estructuras de datos ni a la algorítmia básica así que si no entiendes todavía bien los ejemplos de los patrones es normal.

      Del libro GoF aunque no lo leas entero; es recomendable que te leas la introducción (capitulo 1) que se extienden algunos conceptos generales de la POO.

Publica tu opinión usando tu cuenta de Facebook.

¿Te ha gustado? ¡No te pierdas nada más!

follow us in feedly

Otras webs de Difoosion