Blog

POST #20 : Ruby : Design patterns : Décorateur

Added by Romain GEORGES over 2 years ago

le design pattern décorateur en Ruby

On veut vendre des boites aux lettres aujourd'hui.
Alors on modélise ses produits comme des objets, on va donc créer un objet Bal, avec un prix à l'unité

1 class Bal
2   def prix
3     0.2
4   end
5 end

Par la suite on va vendre des boites avec Anti-virus, comme un produit supplémentaire, l'antivirus change le prix.

1 class BalAV
2   def prix
3     0.3
4   end
5 end

Oui, mais en fait une bal AV c'est une Bal avec une option anti-virus, mais ça reste une boite aux lettres.
Certain me dirons pourquoi on hérite pas avec une surcharge de prix

1 class BalAV< Bal
2   def prix
3     0.3
4   end
5 end

Je dis, "oui mais ça reste une boite aux lettres!"

d'où le décorateur, voila l'outil :

1 module Decorateur
2   def initialize(article)
3     @article = article
4   end
5   def method_missing(method, *args)
6     args.empty? ? @article.send(method) : @article.send(method, args)
7   end
8 end

je définit mes produits supplémentaires comme des Décorateurs, des options sur le produit principale, si vous préféré

 1 class AV
 2   include Decorateur
 3   def prix
 4     @article.prix + 0.1
 5   end
 6 end
 7 
 8 class Webmail
 9   include Decorateur
10   def prix 
11     @article.prix + 0.1
12   end
13 end
14 
15 class IMAP
16   include Decorateur
17 
18   def prix
19     @article.prix + 0.1
20   end
21 end
22 

On va donc facilement créer une boite avec AV, tel que :

1 aBalIMAP =  IMAP.new(Bal.new)
2 p aBalIMAP .prix

On peut même imaginer un Pricer :

1 class MarketPlacePricer
2   def self.premium
3     IMAP.new(Webmail.new(AV.new(Bal.new)))
4   end
5 end
6 
7 p produitpremium = MarketPlacePricer.premium
8 p produitpremium .prix

Encore plus Ruby, on reprend notre class Bal

1 class Bal
2   def prix
3     0.2
4   end
5 end

Mais cette fois-ci on va utiliser des modules :

 1 
 2 module AV
 3   def prix 
 4     super + 0.1
 5   end
 6 end
 7 
 8 module Anti-spam
 9   def prix 
10     super + 0.1
11   end
12 end
13 
14 module IMAP
15   def prix 
16     super + 0.1
17   end
18 end
19 
20 module Webmail
21   def prix 
22     super + 0.1
23   end
24 end

Et donc, simplement :

1 
2 x = Bal.new
3 x.extend AV
4 x.extend Webmail
5 x.extend Anti-spam
6 x.extend Imap
7 p x.prix
8 p x

Also available in: Atom