2010-10-14 4 views
3

Je passe en revue quelques questions de modèle de conception et j'ai regardé la définition et les exemples du motif de décorateur dans le GoF. Il ditGoF explication du motif décorateur est déroutant (ou tout simplement faux)

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Il donne des exemples de décorateurs qui utilisent un héritage qui n'est définitivement pas dynamique, cependant.

NetObjectives commet la même erreur:

http://www.netobjectives.com/PatternRepository/index.php?title=TheDecoratorPattern

La discussion Portland Pattern Repository du décorateur indique qu'il ya confusion au sujet de ce qui est et n'est pas un décorateur

http://c2.com/cgi/wiki?DecoratorPattern

Wikipedia donne un sens à cette contradiction en notant que le délégué à l'intérieur du décorateur devrait être fixé au moment de la construction (d'autres techniques de DI seraient également travail)

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

Tous les exemples du motif décorateur (en Java ou C++) nécessitent une construction statique soit par héritage ou par la mise en œuvre d'une interface. L'explication dans le GoF dit que les responsabilités supplémentaires sont attachées dynamiquement, cependant. Mais c'est tout simplement faux. Les commentaires de PPR parlent de langages dynamiques qui peuvent ajouter des méthodes à l'exécution, mais Java et C++ ne sont pas dynamiques et l'explication de Decorator ne dit pas qu'il est limité aux langages dynamiques comme Groovy et Lisp.

Une explication correcte de Decorator ne dirait-elle pas que dans les langages qui ne supportent pas la création de méthodes dynamiques, les constructions statiques et dyanmiques sont impliquées?

L'explication de GoF est simplement fausse comme le montrent leurs propres exemples, ou ai-je mal compris quelque chose?

+0

Je ne pense pas que l'ajout dynamique de méthodes à l'objet compte comme décoration. Le décorateur et les objets originaux doivent être deux objets distincts. – Thilo

+0

Pourquoi le décorateur et l'objet original doivent-ils être deux objets séparés? Y at-il quelque chose à propos du problème que Decorator résout qui impose une telle exigence sur le modèle de conception? –

Répondre

0

Il semble que l'explication de GoF soit mal écrite. Appeler Decorator une alternative au sous-classement quand leurs exemples sont des sous-classes est très déroutant.

GoF dit que l'objet décoré et ses décorateurs doivent avoir des interfaces conformes. Apparemment c'est une exigence du modèle, et ils le démontrent avec l'héritage. Il y a donc à la fois un composant dynamique et statique dans leur motif Décorateur.

Je pourrais également voir comment vous pourriez inverser le modèle et faire le décorateur (s) un délégué de l'objet décoré, mais cela entraînerait probablement une mise en œuvre alambiquée. Dans un langage dynamique comme Lisp ou Groovy, je pense que vous pourriez simplement fusionner la logique de décoration dans la logique draw() de la classe elle-même. L'exigence de conformité d'interface ne serait pas nécessaire, et il ne serait pas nécessaire d'avoir des classes séparées pour l'objet décoré et le décorateur.

Je vais ajouter l'apprentissage Lisp à ma liste de seaux afin de voir comment les modèles de conception changent dans une langue dynamique.

6

Dynamique Je pense que le mot «dynamique» est venu à signifier quelque chose de différent que lorsque le GOF a écrit le livre. Je suppose que ce qu'ils voulaient dire était 'ajouter un comportement pré/post à un objet sans réellement modifier le code/la définition de l'objet sous-jacent.' Pour les clients, l'objet (décoré ou non) semble être le même. De nos jours, la dynamique est associée à des langages dynamiques et, dans ce sens, signifie un typage lâche et la possibilité d'ajouter des méthodes/comportements à un objet lors de l'exécution.

Alternative à sous-classement

The decorator pattern is an alternative to subclassing. Subclassing adds behavior at compile time, and the change affects all instances of the original class; decorating can provide new behavior at runtime for individual objects.

This difference becomes most important when there are several independent ways of extending functionality. In some object-oriented programming languages, classes cannot be created at runtime, and it is typically not possible to predict, at design time, what combinations of extensions will be needed. This would mean that a new class would have to be made for every possible combination. By contrast, decorators are objects, created at runtime, and can be combined on a per-use basis. -- wikipedia

décorateurs utilisent l'héritage mais ils ne héritent pas de l'objet qu'ils sont la décoration. Ils héritent de l'interface commune afin d'exposer les mêmes méthodes qu'un objet décoré (emprunt d'identité). Ils utilisent la composition pour le comportement - ajouter un comportement pré-post via la délégation.

var dao = new PerformanceTrackingDecorator(new TurboSpeedDecorator(SqlDataAccessObject)) 
// use dao and later.. 
dao = new PerformanceTrackingDecorator(new TurboSpeedDecorator(XmlDataAccessObject)) 
//at runtime, I've added certain behavior to Sql and Xml DAOs 
+2

+1. C'est une implémentation du principe ouvert/fermé. http://en.wikipedia.org/wiki/Open/closed_principle – TrueWill

+0

Si vous regardez les exemples dans GoF, ils héritent de l'objet qu'ils décorent. Ils le font même après avoir dit que Decorator est une alternative au sous-classement. Une autre contradiction dans leur explication de Decorator. –

+0

@Dean, dans les exemples Decorator dans GoF, une classe de composant abstrait a des dérivées qui sont des classes de composants concrètes et une classe décorative abstraite. La classe de décorateur abstrait a des dérivés qui sont des classes de décorateur concret. Les classes de décorateurs n'héritent pas, directement ou indirectement, des classes de composants concrètes. – Huperniketes

Questions connexes