Archives du mot-clé rails

Ruby on Rails: design pattern Factory

Pour traiter du design pattern Factory en Ruby (dans le framework Rails), j’ai repris les exemples faits en PHP il y a déjà 7 ans !

Comme les principes ne diffèrent pas d’un langage à l’autre, seul le code figurera ici. Pour les explications, je vous renvoie au lien ci-dessus !

# on importe de quoi utiliser constantize
require 'active_support/inflector'

# l'interface des fabriques (ici une classe abstraite)
class FabriqueFacture
  def initialize
    raise "Impossible d'instancier la classe abstraite FabriqueFacture"
  end

  def fabriquer
    raise NotImplementedError
  end
end

# les fabriques concrètes
class FabriqueEnteteFacture < FabriqueFacture
  CLASSE_CIBLE = 'Entete'
  private_constant :CLASSE_CIBLE

  def initialize
    # on écrase le constructeur qui lève une exception dans la classe mère
  end

  def fabriquer
    CLASSE_CIBLE.constantize.new
  end
end

class FabriqueCorpsFacture < FabriqueFacture
  CLASSE_CIBLE = 'Corps'
  private_constant :CLASSE_CIBLE

  def initialize(produits)
    @produits = produits
  end

  def fabriquer
    CLASSE_CIBLE.constantize.new(@produits)
  end

  private

  attr_accessor :produits
end

class FabriquePiedPageFacture < FabriqueFacture
  CLASSE_CIBLE = 'PiedPage'
  private_constant :CLASSE_CIBLE

  def initialize
    # même remarque que pour le constructeur de FabriqueEnteteFacture
  end

  def fabriquer
    CLASSE_CIBLE.constantize.new
  end
end

# les produits CONCRETS
class PiedPage
  def formater
    "Je formate mon pied de page"
  end
end

class Entete
  def formater()
    "Je formate mon entête"
  end
end

class Corps
  def initialize (produits)
    @produits = produits
  end

  def formater
    "Je formate mon corps avec mes #{@produits.count} produits"
  end
end

# le code client pour tester toute la chaîne

class Facturation
  def initialize(fabrique_entete, fabrique_corps, fabrique_pied)
    if !((fabrique_entete.is_a? FabriqueFacture) && 
        (fabrique_corps.is_a? FabriqueFacture) && 
        (fabrique_pied.is_a? FabriqueFacture))
      raise "Les fabriques doivent dériver FabriqueFacture"
    end
    @entete = fabrique_entete.fabriquer
    @corps = fabrique_corps.fabriquer
    @pied = fabrique_pied.fabriquer
  end

  def declencher
    puts @entete.formater
    puts @corps.formater
    puts @pied.formater
  end

  private

  attr_accessor :entete, :corps, :pied
end

produits = ['Gourde', 'Ballon', 'Pioche']

facturation = Facturation.new(
    FabriqueEnteteFacture.new,
    FabriqueCorpsFacture.new(produits),
    FabriquePiedPageFacture.new
)

facturation.declencher