41 votes

Équivalent fonctionnel de la décoratrice modèle?

Qu'est-ce que la programmation fonctionnelle équivalent du décorateur?

Par exemple, comment voulez-vous écrire cet exemple en particulier, dans un style fonctionnel?

33voto

Christian Berg Points 7039

En programmation fonctionnelle, vous envelopper d'une fonction donnée dans une nouvelle fonction.

Pour donner artificiel, Clojure exemple similaire à celui indiqué dans votre question:

Mon dessin original fonction:

(defn draw [& args]
  ; do some stuff 
  )

Ma fonction wrappers:

; Add horizontal scrollbar
(defn add-horizontal-scrollbar [draw-fn]
  (fn [& args]
    (draw-horizontal-scrollbar)
    (apply draw-fn args)))


; Add vertical scrollbar
(defn add-vertical-scrollbar [draw-fn]
  (fn [& args]
    (draw-vertical-scrollbar)
    (apply draw-fn args)))

; Add both scrollbars
(defn add-scrollbars [draw-fn]
  (add-vertical-scrollbar (add-horizontal-scrollbar draw-fn)))

Ces renvoyer une nouvelle fonction qui peut être utilisée partout où le dessin original de la fonction est utilisée, mais aussi de dessiner les barres de défilement.

18voto

Marcin Points 25366

Nourrissage des paramètres fonctionnels / composition est l'équivalent le plus proche. Cependant, c'est une erreur de même poser cette question, parce que des modèles existent pour compenser les faiblesses de la langue d'accueil.

Si C++/Java/C#/toute autre pratiquement identique à la langue a une décoration en fonction de la langue, vous n'y pensez pas comme un modèle. Il se trouve que les "modèles" sont des modèles de structuration des systèmes de liaison anticipée objectif impératif langages orientés, généralement sans l'autoboxing, et avec relativement minces protocoles pour la classe racine.

11voto

mikera Points 63056

Vous pouvez "habiller" les fonctions en les enveloppant à l'intérieur d'autres fonctions, en utilisant généralement une certaine forme d'ordre supérieur de la fonction pour effectuer l'emballage.

Exemple Simple en Clojure:

; define a collection with some missing (nil) values
(def nums [1 2 3 4 nil 6 7 nil 9])

; helper higher order function to "wrap" an existing function with an alternative implementation to be used when a certain predicate matches the value
(defn wrap-alternate-handler [pred alternate-f f]
  (fn [x] 
    (if (pred x) 
      (alternate-f x)
      (f x))))

; create a "decorated" increment function that handles nils differently
(def wrapped-inc 
  (wrap-alternate-handler nil? (constantly "Nil found!") inc))

(map wrapped-inc nums)
=> (2 3 4 5 "Nil found!" 7 8 "Nil found!" 10)

Cette technique est largement utilisée dans des fonctionnelles des bibliothèques. Un bon exemple est l' emballage web, les gestionnaires de demandes à l'aide de l'Anneau de middleware - liés exemple des enveloppements de gestion des paramètres du html, demande autour de l'existant gestionnaire.

6voto

dave4420 Points 31298

Quelque chose comme ceci:

class Window w where
    draw :: w -> IO ()
    description :: w -> String

data VerticalScrollingWindow w = VerticalScrollingWindow w

instance Window w => Window (VerticalScrollingWindow w) where
    draw (VerticalScrollingWindow w)
       = draw w >> drawVerticalScrollBar w  -- `drawVerticalScrollBar` defined elsewhere
    description (VerticalScrollingWindow w)
       = description w ++ ", including vertical scrollbars"

6voto

HaskellElephant Points 4985

En Haskell, ce OO schéma traduit assez bien directement, vous avez seulement besoin d'un dictionnaire. Notez que la traduction n'est pas vraiment une bonne idée. Essayer de forcer une OO concept en Haskell est une sorte de backwords, mais vous l'avez demandé si elle est ici.

L'Interface De La Fenêtre

Haskell a des classes, qui a toutes les fonctionnalités d'une Interface et puis certains. Nous utilisons donc la suivante Haskell classe:

class Window w where
  draw :: w -> IO ()
  description :: w -> String

Le Résumé WindowDecorator classe

Celui-ci est un peu plus délicate, car Haskell n'a pas de notion d'héritage. Habituellement, nous ne fournirait pas de ce type et de laisser les décorateurs mettre en oeuvre Window directement, mais permet de suivre l'exemple complètement. Dans cet exemple, un WindowDecorator est une fenêtre avec un constructeur prenant une fenêtre, permet de compléter ce avec une fonction donnant le décoré de la fenêtre.

class WindowDecorator w where
   decorate :: (Window a) => a -> w a
   unDecorate :: (Window a) => w a -> a
   drawDecorated :: w a -> IO ()
   drawDecorated = draw . unDecorate
   decoratedDescription :: w a -> String
   decoratedDescription = description . unDecorate

instance (WindowDecorator w) => Window w where
   draw = drawDecorated
   description = decoratedDescription

Notez que nous fournir une implémentation par défaut de Window, il peut être remplacé, et toutes les instances de l' WindowDecorator sera Window.

Les décorateurs

Faire des décorateurs peut alors être effectuée comme suit:

data VerticalScrollWindow w = VerticalScrollWindow w

instance WindowDecorator VerticalScrollWindow where
  decorate = VerticalScrollWindow
  unDecorate (VerticalScrollWindow w ) = w
  drawDecorated (VerticalScrollWindow w )  = verticalScrollDraw >> draw w

data HorizontalScrollWindow w = HorizontalScrollWindow w

instance WindowDecorator HorizontalScrollWindow where
  decorate = HorizontalScrollWindow
  unDecorate (HorizontalScrollWindow w .. ) = w
  drawDecorated (HorizontalScrollWindow w ..)  = horizontalScrollDraw >> draw w

Finition

Enfin, nous pouvons définir un certain nombre de fenêtres:

data SimpleWindow = SimpleWindow ...

instance Window SimpleWindow where
   draw = simpleDraw
   description = simpleDescription

makeSimpleWindow :: SimpleWindow
makeSimpleWindow = ...

makeSimpleVertical = VerticalScrollWindow . makeSimpleWindow
makeSimpleHorizontal = HorizontalScrollWindow . makeSimpleWindow
makeSimpleBoth = VerticalScrollWindow . HorizontalScrollWindow . makeSimpleWindow

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X