2010-10-12 6 views
5

J'ai un problème dans une de mes classes qui utilise le motif décorateur.Comment gérer cette référence dans le modèle de décorateur

Le problème se pose lorsque l'objet interne utilise la référence "this" dans les appels à d'autres objets. Cela provoque tous les appels de l'objet qui a reçu la référence "this" à être fait directement à l'objet interne, sans passer par le premier externe.

Quelle est la manière habituelle de résoudre ce problème?

Merci.

+2

Il existe plusieurs façons d'interpréter ce que vous avez décrit dans une hiérarchie de classes. _djechelon_ a fourni une réponse donnée à une interprétation de votre question ... J'ai une autre interprétation à l'esprit donc vous voudrez peut-être nous fournir quelques extraits de code. – Isaac

Répondre

2

Les objets ont une valeur implicite: leur identité (peut être testée en appliquant ==). Lorsque vous les enveloppez, vous cachez effectivement cette identité (pire, vous exposez également une identité potentiellement trompeuse, l'identité de l'encapsuleur lui-même). Donc, une approche évidente est de compenser cela en exposant l'identité de l'objet par une autre voie - explicitement. Par exemple. vous pouvez introduire une méthode Object getIdentity(), qui renvoie un objet représentant réellement l'identité voulue, et permettant d'y appliquer ==. L'inconvénient majeur est que vous autorisez toujours == sur le décorateur lui-même, par exemple. un danger:

  • est assez naturel pour être dupé en elle (identity == decorator au lieu de identity == decorator.getIdentity())
  • ne fait silencieusement la mauvaise chose (à comparer avec une exception d'exécution - bon débogage chance que)

le problème serait inexistant si, par exemple, les objets ont une méthode comme:

protected Object getIdentity() { 
    return this; 
} 

Sur quel opérateur == wo uld être défini, de sorte qu'un wrapper pourrait également envelopper l'identité de l'objet enveloppé, au lieu de le remplacer par le sien.

+0

Je pense que c'est comme ça que je vais aller. Ajouter un setIdentity et getIdentity à mon interface de base permettra d'obtenir la fonctionnalité désirée. – monoceres

1

En général, vous ne pouvez pas. Sauf si vous sous-classez votre classe décorée, votre classe interne sera libre d'appeler n'importe quelle méthode en utilisant lui-même comme paramètre, et il n'y a aucun moyen de le changer.

Lors de l'utilisation du motif décorateur, la classe de décorateurs est chargée de transmettre la référence (référençant le décorateur lui-même) à d'autres méthodes. De mon point de vue, le décorateur est la chose la plus similaire à un proxy: l'objet décoré intérieur est complètement enveloppé dans son décorateur (s) et n'est pas directement accessible. Ainsi, vous devez trouver vous-même un moyen d'interdire à votre objet décoré d'accéder directement à d'autres objets et de pouvoir passer this référence

1

Ce que vous décrivez est un mélange de modèles de décorateur et de modèle. Le modèle décorateur vous permet d'ajouter dynamiquement un comportement à un objet (en utilisant un mécanisme similaire à un proxy). Le modèle de modèle casse un algorithme en plusieurs méthodes afin que vous puissiez modifier le comportement d'un objet en substituant des méthodes via le sous-classement, ou dans votre cas, le décorateur. Parce que les décorateurs sont un type de proxy, ils contiennent une référence à l'objet cible (ou un autre décorateur enveloppé n couches autour de l'objet cible). Mais la cible ne suit généralement pas ses décorateurs ou ne fait aucune supposition concernant les décorateurs.Donc, chaque fois que le comportement de l'objet cible est modifié en ajoutant ou supprimant le décorateur le plus externe, votre design devra soit mettre à jour l'objet cible avec une référence à son décorateur externe, soit l'objet cible devra interroger un autre objet. référence du décorateur.

Si l'objet cible peut interroger la référence à la pile d'objets décorés de l'objet qui est chargé de la contenir (quelque chose doit), alors vous êtes probablement d'accord. Sinon, l'objet cible devra peut-être recourir à un délégué ou un médiateur.

Questions connexes