Software Development Notions

Patrón Decorator

June 23, 2020

https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Decorator_UML_class_diagram.svg/400px-Decorator_UML_class_diagram.svg.png

Es un patrón de diseño que nos va a permitir agregar funcionalidad a un objeto existente sin cambiar su estructura. Se busca poder 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, sino otras que la implementan y se asocian a la primera.

Un gran momento para aplicarlo es cuando tenemos una clase que contiene métodos que realizan algo más que lógica de negocio. Dicha lógica no tiene que ver con la intencionalidad del método, pero si es cierto que necesitamos que éste ahí. Buscamos el desacople de funcionalidades que no deberían estar realizando ciertos métodos de una clase, ya que dichos requisitos responden a una forma de implementación que puede variar en el futuro, y el hecho de tenerlo separado en otros métodos que añaden funcionalidad a uno principal, nos permite cambiar fácilmente la funcionalidad, sin tener que realizar el cambio en muchos lugares del código, lo que nos aporta una gran mantenibilidad del código.

La forma típica de implementar éste patrón en Java sería de la siguiente forma. Existe una interfaz

**public** **interface** **Vehicle** {**void** **start**();}

, la cual implementa la clase que especifica

**public** **class** **Car** **implements** Vehicle {
	**public** CarType carType;

	**public** **Car**(CarType carType) {
		**this**.carType = carType;
	}

	**public** **void** **start**() { System.out.print("Arrancando");}
}

, y la clase abstracta que define como se añaden los decoradores a la funcionalidad base.

**public** **abstract** **class** **Decorator** **implements** Vehicle {
	**private** Car car;

	**public** **Decorator**(Car car) {
		**this**.car = car;
	}

	**public** **void** **start**() { car.start();}
}

Trás ésto, todos los decoradores que vayamos a realizar, deben extender de la clase abstracta anterior, y llamar al método base de la clase padre.

public class EnergyDecorator extends Decorator {
    private Car car;

    public EnergyDecorator(Car car) {
        super(car);
        this.car=car;
    }

    public void start() {
        super.start();
        if(car.carType==CarType.ELECTRIC){System.out.println(" con energía eléctrica");}
        if(car.carType==CarType.WIND){System.out.println(" con energía eólica");}
    }
}

Para crear los objetos tendríamos una factoría,

public class CarFactory {
    public static void startCar(){
        new Car(CarType.DEFAULT).start();
    }
    public static void startEnergySpecificCar(CarType carType) {
        new EnergyDecorator(new Car(carType)).start();
    }
}

y finalmente lo comprobaríamos.

public class CarShould {
    @Test
    void start_with_default_car() {
        CarFactory.startCar(); //-> Arrancando
    }

    @Test
    void start_with_electric_car() {
        CarFactory.startEnergySpecificCar(CarType.ELECTRIC); // -> Arrancando con energía eléctrica
    }

    @Test
    void start_with_wind_car() {
        CarFactory.startEnergySpecificCar(CarType.WIND); // -> Arrancando con energía eólica
    }
}

Welcome to my blog about Software Development! I would like to invite you to learning with me 👨‍💻

Search all posts