JavaRush /Blog Java /Random-ES /Patrón decorador de Java

Patrón decorador de Java

Publicado en el grupo Random-ES
En el libro “La cabeza primero. Design Patterns” de Eric Freeman y Elizabeth Robson lo define de la siguiente manera: El patrón Decorator proporciona dinámicamente nuevas capacidades a un objeto y es una alternativa a la subclasificación para ampliar la funcionalidad. Intentemos ver esta definición con más detalle usando un ejemplo. Supongamos que ha creado otra religión moderna más y planea brindarle a la gente los servicios correspondientes. Porque Las tendencias modernas persiguen el vegetarianismo, la ecología, el desarrollo humano y, por alguna razón, la gente no está satisfecha con las religiones "tradicionales" (o al final con el ateísmo), entonces usted, siguiendo la corriente principal, crea otra religión de la Nueva Era (una especie de síntesis de la existente). religiones, tomando de cada una lo que le gusta). Al principio usted proporciona los siguientes servicios: 1. Adivinación 2. Horóscopo Es decir. todo se ve así: Hay una interfaz de servicio con un precio, por supuesto :) y una descripción
public interface Service {
    public double getPrice();
    public String getLabel();
}
y servicios
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
Bueno, en consecuencia, aparecieron 2 órdenes (adivinación con cartas del Tarot y un horóscopo personal del cliente):
public static void main(String[] args) {
    double cost;
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    // И персональный гороскоп
    Service personalHoroscope = new Horoscope("Персональный гороскоп", 9000);
    cost = taro.getPrice() + personalHoroscope.getPrice();

    System.out.println(cost);
}
y el resultado del programa:
10000.0
Todo estaría bien, pero ya hay cientos, si no miles, como usted, y debemos seguir desarrollando la espiritualidad de las personas, de lo contrario ya no estarán interesadas. Por lo tanto, se ofrecieron como opción opciones adicionales a los servicios actuales. Por ejemplo, a la hora de elegir un servicio de adivinación (Tarot o posos de café), como opción adicional puedes solicitar las características de los chakras o del aura (con su propio coste para cada uno). ¿Cómo podría implementarse esto para no realizar cambios en las clases de servicio existentes, donde ya todo está configurado y calculado correctamente? Puedes crear clases adicionales de Adivinación + Chakras o Adivinación + Aura a la Adivinación actual:
public class Divination implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithAura implements Service {
    // Здесь своя стоимость и другие методы
}
o simplemente usar subclases, es decir extender la clase principal a la clase secundaria
public class DivinationWithAura extends Divination {
    public DivinationWithAura(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras extends Divination {
    public DivinationWithChakras(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
Pero las desventajas son inmediatamente visibles, al desarrollar la espiritualidad de todo el mundo, es posible que tengamos nuevas opciones adicionales, lo que significa nuevas clases, y si aún necesitamos combinar las actuales, entonces las clases crecerán rápidamente, al menos ya no las tenemos. Basta de clases de adivinación con dos opciones juntas, y no por separado:
public class DivinationWithChakrasAndAura implements Service {
    // Здесь своя стоимость и другие методы
}
Aquí es donde puede utilizar el patrón Decorador "salvador" en Java. Para hacer esto, crearemos una clase para opciones adicionales, que también implementará el Servicio, pero también contendrá el Servicio. Y en consecuencia, cuando necesitemos realizar un pedido de adivinación e incluso con 2 opciones juntas, se verá así: La interfaz es como estaba desde el principio.
public interface Service {
    public double getPrice();
    public String getLabel();
}
2 clases de servicios, igual que antes:
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
Decorador para opciones adicionales
public class OptionDecorator implements Service {
    private Service service;
    private String label;
    private double price;

    public OptionDecorator(Service service, String label, double price) {
        this.service = service;
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price + service.getPrice();
    }

    public String getLabel() {
        return this.label + service.getLabel();
    }
}
Y las opciones en sí (2 hasta ahora):
public class Aura extends OptionDecorator {
    public Aura(Service service) {
        super(service, "Характеристика ауры", 1500);
    }
}
public class Chakra extends OptionDecorator {
    public Chakra(Service service) {
        super(service, "Характеристика чакр", 500);
    }
}
Bueno, el pedido en sí.
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());
}
3000.0
que da el resultado de la suma del servicio principal y 2 opciones adicionales. Esto significa que no hay necesidad de cada adicional opción (o una combinación de ambas) para crear una nueva clase. Además, estas opciones se pueden aplicar no solo al servicio de Adivinación, sino también al servicio de Horóscopo. Por lo tanto, cuando en un futuro próximo necesitemos implementar las siguientes opciones adicionales: - compatibilidad de socios de avatar en las redes sociales - mejorar el flujo de caja a través de canalización remota, necesitaremos escribir solo 2 clases adicionales:
public class Channeling extends OptionDecorator {
    public Channeling(Service service) {
        super(service, "Полет в Поле Чудес", 99999);
    }
}
public class Avatar extends OptionDecorator {
    public Avatar(Service service) {
        super(service, "Ваша любовь в соц сетях", 5555);
    }
}
y puedes agregarlos a cualquier servicio:
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());

    // Гороскоп
    Service horoscope = new Horoscope("Персональный гороскоп", 1000);
    Service channenling = new Channeling(horoscope);
    Service avatar = new Avatar(channenling);

    // И общая стоимость
    System.out.println(avatar.getPrice());
}
y el resultado del programa (que necesitamos):
3000.0
106554.0
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION