Comprendre le "motif décorateur" avec un exemple du monde réel

j'étudiais le motif décorateur comme documenté dans GOF .

s'il vous Plaît, m'aider à comprendre le Décorateur Modèle . Quelqu'un pourrait-il donner un exemple de cas d'utilisation où cela est utile dans le monde réel?

149
demandé sur ROMANIA_engineer 2010-04-25 10:36:47

12 réponses

motif décorateur atteint un seul objectif d'ajouter dynamiquement responsabilités à n'importe quel objet.

considérez un cas de Pizzeria. Dans la pizzeria, ils vendront peu de variétés de pizza et ils fourniront également des garnitures dans le menu. Imaginez maintenant une situation dans laquelle si le magasin de pizza doit fournir des prix pour chaque combinaison de pizza et de garniture. Même s'Il ya quatre pizzas de base et 8 différentes garnitures, l'application deviendrait fou en maintenant toute cette combinaison de béton de pizzas et garnitures.

voici le motif décorateur.

selon le modèle de décorateur, vous réaliserez des garnitures car les décorateurs et les pizzas seront décorées par les décorateurs de ces garnitures. Pratiquement chaque client voudrait garnitures de son désir et facture finale-montant sera composé des pizzas de base et en outre commandé garnitures. Chacun décorateur de garniture serait au courant sur les pizzas qu'il est la décoration et il est prix. GetPrice () méthode de la garniture objet retournerait le prix cumulatif de la pizza et de la garniture.

EDIT

voici un exemple de code d'explication ci-dessus.

public abstract class BasePizza
{
    protected double myPrice;

    public virtual double GetPrice()
    {
        return this.myPrice;
    }
}

public abstract class ToppingsDecorator : BasePizza
{
    protected BasePizza pizza;
    public ToppingsDecorator(BasePizza pizzaToDecorate)
    {
        this.pizza = pizzaToDecorate;
    }

    public override double GetPrice()
    {
        return (this.pizza.GetPrice() + this.myPrice);
    }
}

class Program
{
    [STAThread]
    static void Main()
    {
        //Client-code
        Margherita pizza = new Margherita();
        Console.WriteLine("Plain Margherita: " + pizza.GetPrice().ToString());

        ExtraCheeseTopping moreCheese = new ExtraCheeseTopping(pizza);
        ExtraCheeseTopping someMoreCheese = new ExtraCheeseTopping(moreCheese);
        Console.WriteLine("Plain Margherita with double extra cheese: " + someMoreCheese.GetPrice().ToString());

        MushroomTopping moreMushroom = new MushroomTopping(someMoreCheese);
        Console.WriteLine("Plain Margherita with double extra cheese with mushroom: " + moreMushroom.GetPrice().ToString());

        JalapenoTopping moreJalapeno = new JalapenoTopping(moreMushroom);
        Console.WriteLine("Plain Margherita with double extra cheese with mushroom with Jalapeno: " + moreJalapeno.GetPrice().ToString());

        Console.ReadLine();
    }
}

public class Margherita : BasePizza
{
    public Margherita()
    {
        this.myPrice = 6.99;
    }
}

public class Gourmet : BasePizza
{
    public Gourmet()
    {
        this.myPrice = 7.49;
    }
}

public class ExtraCheeseTopping : ToppingsDecorator
{
    public ExtraCheeseTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 0.99;
    }
}

public class MushroomTopping : ToppingsDecorator
{
    public MushroomTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 1.49;
    }
}

public class JalapenoTopping : ToppingsDecorator
{
    public JalapenoTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 1.49;
    }
}
206
répondu this. __curious_geek 2016-03-23 18:12:45

c'est un exemple simple de l'ajout d'un nouveau comportement à un objet existant dynamiquement, ou le motif décorateur. En raison de la nature des langages dynamiques tels que Javascript, Ce modèle devient une partie du langage lui-même.

// create a message object
var message = {
    text: "Lorem ipsum dolor sit amet, consectetur adipisicing elit..."
};

// add logging behavior to the message object dynamically
message.log = function() {
    console.log(this.text);
};

// use the newly added behavior to log text
​message.log();​ // Loren ipsum...​​​​​​​​​​​​​​​
28
répondu Anurag 2017-06-11 19:11:42

il est intéressant de noter que le modèle D'E/S Java est basé sur le motif décorateur. La superposition de ce lecteur au-dessus de ce lecteur au-dessus de...est un exemple réel de décorateur.

16
répondu frankc 2010-04-26 14:39:08

exemple-scénario-disons que vous écrivez un module de cryptage. Ce cryptage peut crypter le fichier clair en utilisant DES-Data encryption standard. De même, dans un système, vous pouvez avoir le cryptage comme AES - Advance encryption standard. En outre, vous pouvez avoir la combinaison de cryptage - D'abord DES, Puis AES. Ou vous pouvez avoir d'abord AES, puis DES.

Discussion-Comment allez-vous répondre à cette situation? Vous ne pouvez pas continuer à créer l'objet de telles combinaisons-pour exemple-AES et DES - total de 4 combinaisons. Ainsi, vous devez avoir 4 objets individuels cela va devenir complexe que le type de cryptage va augmenter.

Solution - garder la construction de la pile-combinaisons en fonction du besoin - au moment de l'exécution. Un autre avantage de cette approche de pile est que vous pouvez le décompresser facilement.

Voici la solution-en C++.

tout d'Abord, vous avez besoin d'une classe de base - une unité fondamentale de la pile. Vous pouvez penser que la base de la pile. Dans cet exemple, le fichier est clair. Suivons toujours le polymorphisme. Faire d'abord une classe d'interface de cette unité fondamentale. De cette façon,vous pouvez mettre en place comme vous le souhaitez. De plus, vous n'avez pas besoin de penser à la dépendance tout en incluant cette unité fondamentale.

Voici la classe d'interface -

class IclearData
{
public:

    virtual std::string getData() = 0;
    virtual ~IclearData() = 0;
};

IclearData::~IclearData()
{
    std::cout<<"Destructor called of IclearData"<<std::endl;
}

maintenant, mettre en œuvre cette classe d'interface -

class clearData:public IclearData
{
private:

    std::string m_data;

    clearData();

    void setData(std::string data)
        {
            m_data = data;
        }

public:

    std::string getData()
    {
        return m_data;
    }

    clearData(std::string data)
    {
        setData(data);
    }

    ~clearData()
    {
        std::cout<<"Destructor of clear Data Invoked"<<std::endl;
    }

};

maintenant, créer une classe de décoration abstraite - qui peut être étendue pour créer n'importe quel type de saveurs - ici la saveur est le type de cryptage. Cette classe de décoration abstraite est liée à la classe de base. Ainsi, le décorateur "est une" sorte de classe d'interface. Ainsi, vous devez utiliser l'héritage.

class encryptionDecorator: public IclearData
{

protected:
    IclearData *p_mclearData;

    encryptionDecorator()
    {
      std::cout<<"Encryption Decorator Abstract class called"<<std::endl;
    }

public:

    std::string getData()
    {
        return p_mclearData->getData();
    }

    encryptionDecorator(IclearData *clearData)
    {
        p_mclearData = clearData;
    }

    virtual std::string showDecryptedData() = 0;

    virtual ~encryptionDecorator() = 0;

};

encryptionDecorator::~encryptionDecorator()
{
    std::cout<<"Encryption Decorator Destructor called"<<std::endl;
}

maintenant, faisons une classe de décorateur de béton - Type de cryptage-AES -

const std::string aesEncrypt = "AES Encrypted ";

class aes: public encryptionDecorator
{

private:

    std::string m_aesData;

    aes();

public:

    aes(IclearData *pClearData): m_aesData(aesEncrypt)
    {
        p_mclearData = pClearData;
        m_aesData.append(p_mclearData->getData());
    }

    std::string getData()
        {
            return m_aesData;
        }

    std::string showDecryptedData(void)
    {
        m_aesData.erase(0,m_aesData.length());
        return m_aesData;
    }

};

maintenant, disons que le type de décorateur est DES -

const std:: string desEncrypt = " des Crypted ";

class des: public encryptionDecorator
{

private:

    std::string m_desData;

    des();

public:

    des(IclearData *pClearData): m_desData(desEncrypt)
    {
        p_mclearData = pClearData;
        m_desData.append(p_mclearData->getData());
    }

    std::string getData(void)
        {
            return m_desData;
        }

    std::string showDecryptedData(void)
    {
        m_desData.erase(0,desEncrypt.length());
        return m_desData;
    }

};

faisons un code client pour utiliser cette classe de décorateur -

int main()
{
    IclearData *pData = new clearData("HELLO_CLEAR_DATA");

    std::cout<<pData->getData()<<std::endl;


    encryptionDecorator *pAesData = new aes(pData);

    std::cout<<pAesData->getData()<<std::endl;

    encryptionDecorator *pDesData = new des(pAesData);

    std::cout<<pDesData->getData()<<std::endl;

    /** unwind the decorator stack ***/
    std::cout<<pDesData->showDecryptedData()<<std::endl;

    delete pDesData;
    delete pAesData;
    delete pData;

    return 0;
}

, Vous verrez les résultats suivants -

HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
DES Encrypted AES Encrypted HELLO_CLEAR_DATA
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Destructor called
Destructor called of IclearData
Encryption Decorator Destructor called
Destructor called of IclearData
Destructor of clear Data Invoked
Destructor called of IclearData

voici le diagramme UML - représentation de classe de celui-ci. Dans le cas, vous voulez sauter le code et se concentrer sur l'aspect de la conception.

enter image description here

7
répondu dexterous_stranger 2014-12-02 07:24:59

qu'est-Ce que Décorateur en Java.

La définition formelle de l'Décorateur modèle à partir du GoF livre (Design Patterns: Elements de Logiciels Orientés Objets Réutilisables, 1995, Pearson Education, Inc. La publication en tant Pearson Addison Wesley) vous dit que vous pouvez,

" attribuer dynamiquement des responsabilités supplémentaires à un objet. Décorateur offrir une solution de rechange souple au sous-classement pour étendre la fonctionnalité."

Disons qu'on a une Pizza et qu'on veut la décorer avec des garnitures comme du poulet Masala, de l'oignon et du fromage Mozzarella. Nous allons voir comment mettre en œuvre en Java ...

programme pour montrer comment mettre en œuvre décorateur modèle de conception en Java.

Pizza.Java:

<!-- language-all: lang-html -->

package com.hubberspot.designpattern.structural.decorator;

public class Pizza {

public Pizza() {

}

public String description(){
    return "Pizza";
}

}



package com.hubberspot.designpattern.structural.decorator;

public abstract class PizzaToppings extends Pizza {

public abstract String description();

}

package com.hubberspot.designpattern.structural.decorator;

public class ChickenMasala extends PizzaToppings {

private Pizza pizza;

public ChickenMasala(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + " with chicken masala, ";
}

}



package com.hubberspot.designpattern.structural.decorator;

public class MozzarellaCheese extends PizzaToppings {

private Pizza pizza;

public MozzarellaCheese(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + "and mozzarella cheese.";
}
}



package com.hubberspot.designpattern.structural.decorator;

public class Onion extends PizzaToppings {

private Pizza pizza;

public Onion(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + "onions, ";
}

}



package com.hubberspot.designpattern.structural.decorator;

public class TestDecorator {

public static void main(String[] args) {

    Pizza pizza = new Pizza();

    pizza = new ChickenMasala(pizza);
    pizza = new Onion(pizza);
    pizza = new MozzarellaCheese(pizza);

    System.out.println("You're getting " + pizza.description());

}

}
3
répondu Jonty 2013-06-22 16:49:24

Decorator pattern vous aide à modifier ou configurer une fonctionnalité de votre objet en enchaînant avec d'autres sous-classes similaires de cet objet.

le meilleur exemple serait les classes InputStream et OutputStream en java.colis io

    File file=new File("target","test.txt");
    FileOutputStream fos=new FileOutputStream(file);
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    ObjectOutputStream oos=new ObjectOutputStream(bos);


    oos.write(5);
    oos.writeBoolean(true);
    oos.writeBytes("decorator pattern was here.");


//... then close the streams of course.
3
répondu huseyin 2017-08-08 19:45:48

j'ai beaucoup utilisé le motif décorateur dans mon travail. J'ai fait un post sur mon blog sur la façon de l'utiliser avec la journalisation.

2
répondu Ismael 2017-05-20 23:42:26

décorateur:

  1. ajouter comportement à l'objet au temps d'exécution . L'héritage est la clé pour atteindre cette fonctionnalité, qui est à la fois l'avantage et l'inconvénient de ce modèle.
  2. il améliore le comportement de l'interface.
  3. Décorateur peut être considéré comme un dégénéré Composite avec un seul composant. Toutefois, un Décorateur ajoute des responsabilités supplémentaires - il n'est pas destiné à l'agrégation d'objets.
  4. la classe Decorator déclare une relation de composition à L'interface LCD (plus petit dénominateur de classe), et ce membre de données est initialisé dans son constructeur.
  5. Décorateur est conçu pour vous permettre d'ajouter des responsabilités aux objets sans sous-classe

Consultez sourcemaking de l'article pour plus d' détail.

Decorator (Abstract) : il s'agit d'une classe abstraite/interface, qui implémente l'interface des composants. Il contient L'interface des composants. En l'absence de cette classe, vous avez besoin de beaucoup de sous-classes de ConcreteDecorators pour différentes combinaisons. La Composition du composant réduit les sous-classes inutiles.

exemple JDK:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
while(bis.available()>0)
{
        char c = (char)bis.read();
        System.out.println("Char: "+c);;
}

Regardez ci-dessous la question SE pour le diagramme et le code UML exemple.

motif décorateur pour IO

articles utiles:

journaldev

wikipedia

mot Réel exemple de la Décoratrice modèle: VendingMachineDecorator a été expliqué @

quand utiliser le motif décorateur?

Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.decorateBeverage();

beverage = new SugarDecorator(new LemonDecorator(new Coffee("Cappuccino")));
beverage.decorateBeverage();

dans l'exemple ci-dessus, le thé ou le café ( boisson) a été décoré de sucre et de citron.

2
répondu Ravindra babu 2017-09-22 15:49:32

motif décorateur atteint un seul objectif de ajoutant dynamiquement des responsabilités à tout objet .

Java I/O Model est basé sur le motif décorateur.

Java IO as decorator pattern

2
répondu ChandraBhan Singh 2018-07-29 06:28:01

le motif décorateur vous permet d'ajouter dynamiquement un comportement aux objets.

prenons un exemple où vous devez construire une application qui calcule le prix de différents types de hamburgers. Vous avez besoin de gérer différentes variantes de hamburgers, tels que "grand" ou "avec fromage", dont chacun a un prix par rapport au hamburger de base. Par exemple: ajoutez 10 $pour le hamburger au fromage, 15 $ supplémentaires pour le grand hamburger, etc.

In ce cas, vous pourriez être tenté de créer des sous-classes pour gérer ces. Nous pourrions exprimer ceci dans Ruby comme:

class Burger
  def price
    50
  end
end

class BurgerWithCheese < Burger
  def price
    super + 15
  end
end

dans l'exemple ci-dessus, la classe BurgerWithCheese hérite de Burger, et remplace la méthode du prix pour ajouter $15 au prix défini dans la classe super. Vous pouvez aussi créer une classe de hamburgers et définir le prix relatif au Hamburger. Mais vous avez aussi besoin de définir une nouvelle classe pour la combinaison de la "grande" et "fromage".

Que se passe-t-il si on doit servir "burger avec des frites"? Nous avons déjà 4 classes pour gérer ces combinaisons, et nous aurons besoin d'ajouter 4 autres pour gérer toutes les combinaisons des 3 propriétés - "grand", "avec fromage" et "avec des frites". On a besoin de 8 cours maintenant. Ajoutez une autre propriété et nous en aurons besoin de 16. Ce nombre augmentera de 2^N.

essayons plutôt de définir un BurgerDecorator qui prend un objet Burger:

class BurgerDecorator
  def initialize(burger)
    self.burger = burger
  end
end

class BurgerWithCheese < BurgerDecorator
  def price
    self.burger.price + 15
  end
end

burger = Burger.new
cheese_burger = BurgerWithCheese.new(burger)
cheese_burger.price   # => 65

Dans l'exemple ci-dessus, nous avons créé une classe BurgerDecorator, dont BurgerWithCheese classe hérite. Nous pouvons également représenter la variation" large " en créant la classe LargeBurger. Maintenant, nous pourrions définir un grand hamburger avec du fromage à l'écoulement comme:

b = LargeBurger.new(cheese_burger)
b.price  # => 50 + 15 + 20 = 85

rappelez-vous comment l'utilisation de l'héritage pour ajouter la variation "avec des frites" impliquerait l'ajout de 4 sous-classes supplémentaires? Avec les décorateurs, nous créerions juste une nouvelle classe, BurgerWithFries, pour gérer la nouvelle variation et gérer cela à l'exécution. Chaque nouvelle propriété ont juste besoin de plus de décorateur pour couvrir toutes les permutations.

PS. C'est la version courte d'un article que j'ai écrit sur en utilisant le motif décorateur dans Ruby , que vous pouvez lire si vous souhaitez trouver des exemples plus détaillés.

1
répondu Nithin 2015-03-23 18:14:21

il y a un exemple sur Wikipedia sur la décoration d'une fenêtre avec scrollbar:

http://en.wikipedia.org/wiki/Decorator_pattern

voici un autre exemple très "réel" de "membre D'équipe, chef d'équipe et directeur", qui illustre que le motif Décorateur est irremplaçable avec un héritage simple:

https://zishanbilal.wordpress.com/2011/04/28/design-patterns-by-examples-decorator-pattern /

1
répondu gm2008 2016-12-27 21:11:35

Décorator Design Pattern : Ce modèle permet de modifier les caractéristiques d'un objet lors de l'exécution. Il donne différentes saveurs à un objet et donne la flexibilité de choisir les ingrédients que nous voulons utiliser dans cette saveur.

Exemple De La Vie Réelle: Disons que vous avez un siège cabine principal dans un vol. Maintenant, vous êtes autorisé à choisir plusieurs commodités avec le siège. Chaque installation a son propre coût associé. Maintenant, si un utilisateur choisit Wifi et nourriture de qualité supérieure, il / elle sera facturé pour le siège + wifi + nourriture de qualité supérieure.

enter image description here

Dans ce cas, décorateur peut vraiment nous aider. Visitez le lien ci-dessus pour en savoir plus sur le modèle de décorateur et la mise en œuvre d'un exemple de la vie réelle.

0
répondu Ajit Singh 2015-10-30 14:40:10