2012-08-08 4 views
2

Je pense à un mécanisme général pour garder une trace des changements de tous les membres d'un objet. L'idée est essentiellement de sauvegarder un horodatage à un membre lastModified à chaque fois qu'un set est appelé.Suivre les modifications d'un objet

Mon idée jusqu'à présent était d'avoir une classe parente (pseudo code ici)

class Tracker { 
    time lastModified; 
    void onChildSet() { 
     lastModified = NOW(); 
    } 
} 

et d'hériter de cela pour mon objet particulier

public class Object extends Tracker { 
    sometype member; 
    void setMember(sometype value) { 
     member = value; 
     onChildSet(); 
    } 
} 

Ce que je n'aime pas ce approche est, que je ne vois pas comment je pourrais éviter la nécessité de l'appel explicite de onChildSet() de la classe parente. En fait, je cherche un moyen d'avoir lastModified mis à jour automatiquement sans avoir à écrire du code. Y a-t-il un concept pour y parvenir?

+0

quelle langue voulez-vous implémenter dans Java? – hackattack

+1

Peut être un bon endroit pour utiliser un proxy que vous construisez dynamiquement. –

+0

@hackattack: Malheureusement, c'est en quelque sorte ouvert;). J'adorerais une solution disponible dans d'autres langues, pas seulement Java. –

Répondre

1

La plupart des langages dynamiques ont un moyen d'intercepter les appels de méthodes. Par exemple, tous les objets ruby ​​ont une méthode "method_missing" qui est appelée à chaque fois qu'une méthode est appelée sur un objet qui n'est pas défini. Vous pouvez utiliser cette fonctionnalité pour configurer un objet proxy pour suivre une valeur lastModified. Un autre langage dynamique, Actionscript 3.0 a une classe Proxy dans l'API. Encore une fois, vous pouvez utiliser cette classe de proxy pour intercepter les appels de fonction. Malheureusement, l'utilisation de procurations comme celle-ci signifie que vous devez modifier la façon dont vous définissez vos méthodes. Dans le cas de ruby, method_missing n'est évidemment appelé que lorsque la méthode n'existe pas. Cela signifie que vous devez définir vos méthodes sur un objet qui est ensuite enveloppé par la classe proxy. Regardez l'exemple que j'ai mis en place dans AS3. Pour qu'une propriété soit suivie, elle doit être définie par la méthode trackSet, nous ne pouvons pas définir la méthode directement sur la classe MyObject. trackSet stocke le nom de la propriété dans un objet ainsi qu'une fonction de rappel. Lorsque setProperty est appelé sur la classe proxy, le nom de la propriété est vérifié par rapport à l'objet setters et si existe lastModified est mis à jour pour cette propriété et que callback est appelé.

package { 

    import flash.utils.Proxy; 
    import flash.utils.flash_proxy; 

    public dynamic class Tracker extends Proxy { 

     private var setters : Object; 

     public function Tracker() { 
      setters = { }; 
     } 

     public function getLastModified(name : String) : Number { 
      return setters[name] ? setters[name].lastModified : 0; 
     } 

     protected function trackSet(name : String, fn : Function) : void { 
      setters[name] = { 
       lastModified: 0, 
       setter: fn 
      }; 
     } 

     override flash_proxy function setProperty(name : *, value : *) : void { 
      if(!setters[name]) return; 
      setters[name].lastModified = new Date().time; 
      setters[name].setter(value); 
     } 

    } 
} 

-

package { 

    public dynamic class MyObject extends Tracker { 

     public function MyObject() { 
      trackSet('member', setMember); 
     } 

     private function setMember(val : String) : void { 
      trace('set member =', val); 
     } 

    } 
} 

-

var obj : MyObject = new MyObject(); 
obj.member = 'monkey'; 
trace('member getlast modified at', obj.getLastModified('member')); 
+0

Un grand merci pour votre réponse très détaillée et l'exemple de code complet! –

1

utilisez InvocationHandler. vous pouvez également faire la même chose avec l'instrumentation bytecode mais InvocationHandler est plus simple

+0

Cela ressemble à une excellente suggestion pour Java - je vais considérer cela. Merci! –

+0

j'ai oublié un autre: AOP – piotrek

Questions connexes