JavaRush /Blog Java /Random-FR /Modèle de décorateur Java

Modèle de décorateur Java

Publié dans le groupe Random-FR
Dans le livre « La tête d’abord. Design Patterns » d'Eric Freeman et Elizabeth Robson le définit comme suit : Le modèle Decorator fournit dynamiquement de nouvelles capacités à un objet et constitue une alternative au sous-classement pour étendre les fonctionnalités. Essayons d'examiner cette définition plus en détail à l'aide d'un exemple. Supposons que vous ayez créé une autre religion moderne et que vous envisagez de fournir aux gens les services correspondants. Parce que les tendances modernes poursuivent le végétarisme, l'écologie, le développement humain et, pour une raison quelconque, les gens ne sont pas satisfaits des religions « traditionnelles » (ou de l'athéisme en fin de compte), alors vous, en suivant le courant dominant, créez une autre religion New Age (une sorte de synthèse des religions existantes). religions, prenant à chacune ce qui lui plaît). Au début, vous fournissez les services suivants : 1. La bonne aventure 2. Horoscope C'est-à-dire. tout ressemble à ça : Il y a une interface de service avec un prix bien sûr :) et une description
public interface Service {
    public double getPrice();
    public String getLabel();
}
Et services
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;
    }
}
Eh bien, en conséquence, 2 commandes sont apparues (la bonne aventure avec des cartes de Tarot et un horoscope personnel du client) :
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);
}
et le résultat du programme :
10000.0
Tout irait bien, mais il y en a déjà des centaines, voire des milliers, comme vous, et il faut continuer à développer la spiritualité des gens, sinon ils ne s'intéressent plus. Par conséquent, des options supplémentaires aux services actuels ont été proposées en option. Par exemple, lors du choix d'un service de divination (Tarot ou marc de café), vous pouvez commander en option supplémentaire les caractéristiques des chakras ou de l'aura (avec leur propre coût pour chacun). Comment cela pourrait-il être implémenté afin de ne pas apporter de modifications aux classes de services existantes, où tout est déjà configuré et calculé correctement. Vous pouvez créer des classes supplémentaires Divination + Chakras ou Divination + Aura à la Divination actuelle :
public class Divination implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithAura implements Service {
    // Здесь своя стоимость и другие методы
}
ou utilisez simplement le sous-classement, c'est-à-dire étendre la classe parent à la classe enfant
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);
    }
    // Здесь своя стоимость и другие методы
}
Mais les inconvénients sont immédiatement visibles, développant la spiritualité du monde entier, nous pouvons avoir de nouvelles options supplémentaires, ce qui signifie de nouvelles classes, et si nous avons encore besoin de combiner les classes actuelles, alors les classes grandiront rapidement, du moins nous n'en aurons plus. assez de classe de divination avec deux options ensemble, et non séparément séparément :
public class DivinationWithChakrasAndAura implements Service {
    // Здесь своя стоимость и другие методы
}
C’est ici que vous pouvez utiliser le modèle Decorator très « économe » en Java. Pour ce faire, nous allons créer une classe pour des options supplémentaires, qui implémentera également Service, mais contiendra également Service. Et en conséquence, lorsque nous aurons besoin de passer une commande de divination et même avec 2 options ensemble, cela ressemblera à ceci : L'interface est la même qu'elle était depuis le tout début
public interface Service {
    public double getPrice();
    public String getLabel();
}
2 classes de services, les mêmes que précédemment :
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;
    }
}
Décorateur pour des options supplémentaires
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();
    }
}
Et les options elles-mêmes (2 jusqu'à présent) :
public class Aura extends OptionDecorator {
    public Aura(Service service) {
        super(service, "Характеристика ауры", 1500);
    }
}
public class Chakra extends OptionDecorator {
    public Chakra(Service service) {
        super(service, "Характеристика чакр", 500);
    }
}
Eh bien, la commande elle-même
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
ce qui donne le résultat de la somme de la prestation principale et de 2 options supplémentaires. Cela signifie qu'il n'est pas nécessaire d'effectuer des opérations supplémentaires option (ou une combinaison des deux) pour créer une nouvelle classe. De plus, ces options peuvent être appliquées non seulement au service de divination, mais également au service Horoscope. Ainsi, lorsque dans un avenir proche nous devrons mettre en œuvre les options supplémentaires suivantes : - compatibilité des partenaires avatars sur les réseaux sociaux - amélioration de la trésorerie grâce à la canalisation à distance, nous n'aurons besoin d'écrire que 2 classes supplémentaires :
public class Channeling extends OptionDecorator {
    public Channeling(Service service) {
        super(service, "Полет в Поле Чудес", 99999);
    }
}
public class Avatar extends OptionDecorator {
    public Avatar(Service service) {
        super(service, "Ваша любовь в соц сетях", 5555);
    }
}
et vous pouvez les ajouter à n'importe quel service :
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());
}
et le résultat du programme (dont nous avons besoin) :
3000.0
106554.0
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION