Question

En supposant que je possède une classe nommée A , et que je souhaite utiliser le modèle de conception de décorateur. Corrigez-moi si je me trompe, mais pour que cela fonctionne, nous devrons créer une classe de décorateur, disons ADecorator , qui contiendra une référence à une instance A . , et tous les autres décorateurs étendront cela pour ajouter des fonctionnalités.

Je ne comprends pas pourquoi nous devons créer une classe de décorateur au lieu d'utiliser une instance A ?

Était-ce utile?

La solution

Le modèle de décorateur est utilisé pour ajouter des fonctionnalités aux objets de manière dynamique (c'est-à-dire au moment de l'exécution). Normalement, les capacités de l'objet seront corrigées lorsque vous écrivez la classe. Mais un point important est que la fonctionnalité de l'objet est étendue de manière transparente pour le client de l'objet car il implémente la même interface que l'objet d'origine délègue la responsabilité à l'objet décoré.

Le modèle de décorateur fonctionne dans les scénarios dans lesquels un objet peut comporter de nombreuses fonctionnalités facultatives. Sans le motif décoratif, vous devrez créer une classe différente pour chaque configuration d'objet-option. Un exemple assez utile provient du livre Les modèles de conception Head First de O'Reilly. Il utilise un exemple de café ressemblant à StarBucks.

Vous avez donc le café de base avec une méthode telle que le coût.

public double cost(){
     return 3.45;
}

Ensuite, le client peut ajouter de la crème à un coût de 0,35; vous créez donc une classe CoffeeCream avec la méthode du coût:

public double cost(){
    return 3.80;
}

Ensuite, le client voudra peut-être du moka (0,5 €) et du moka avec de la crème ou du moka sans crème. Donc, vous créez des classes CoffeeMochaCream et CoffeeMocha. Ensuite, un client souhaite une double crème afin de créer une classe CoffeeCreamCream & # 8230; etc. Vous vous retrouvez avec une explosion de classe. S'il vous plaît excuser le mauvais exemple utilisé. Il est un peu tard et je sais que c'est trivial, mais cela exprime bien l'idée.

Vous pouvez créer une classe abstraite Item avec une méthode de coût abstrait:

public abstract class Item{
    public abstract double cost();
}

Et vous pouvez créer une classe de café en béton qui s'étend à l'élément:

public class Coffee extends Item{
    public double cost(){
       return 3.45;
    }
}

Vous créez ensuite un CoffeeDecorator qui étend la même interface et contient un élément.

public abstract class CoffeeDecorator extends Item{
     private Item item;
     ...
}

Vous pouvez ensuite créer des décorateurs en béton pour chaque option:

public class Mocha extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.5;
   }

}

Notez que le décorateur ne se soucie pas du type d’objet qu’il enveloppe tant qu’il s’agit d’un objet. Il utilise le coût () de l'objet et ajoute simplement son propre coût.

public class Cream extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.35;
   }

}

Il est maintenant possible pour un grand nombre de configurations avec ces quelques classes: par exemple

 Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream

ou

 Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream

Et ainsi de suite.

Autres conseils

Je ne peux pas l'expliquer mieux que l'article wikipedia .

BTW, si vous débutez dans les patterns, le livre Head First Design Patterns est phénoménal . Cela simplifie vraiment la compréhension des concepts et permet de mettre en contraste et de comparer des modèles similaires d’une manière ridiculement facile à comprendre.

Dans certaines langues (comme Ruby ou JavaScript), vous pouvez simplement ajouter de nouvelles fonctionnalités à une instance de type A. Je remarque que votre question porte la mention Java. Je suppose donc que vous demandez pourquoi vous ne pouvez pas le faire en Java. La raison en est que Java est typé de manière statique. Une instance A ne peut avoir que les méthodes définies ou héritées par la classe A. Par conséquent, si vous souhaitez donner à une instance A une méthode non définie par A, cette nouvelle méthode doit être définie dans une autre classe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top