2010-09-25 3 views
0

Disons que j'ai un paquet appelé 'animal' incluant la classe parentale, le chat s'étend de l'animal, le chien s'étend de l'animal, aussi. Animal, cependant, est conçu comme ceci:Comment modifier une méthode de package prédéfinie en dehors du package?

class Animal { 
    int amount; 
    Animal next; // Then a constructor initializes these. 

    drinkWater(int n) { ... } 
} 

Cat & cours chiens suivent cette structure:

class Cat extends Animal { 
    Cat(int amount, Animal next) { 
    super(amount, next); 
    } 

    @Override 
    drinkWater(int n) { .. } 
} 

Chacun d'eux a la méthode, Drinkwater() comme ceci:

public void drinkWwater(int n) { 
    amount -= n; 
    if (amount < 0) amount = 0; 
    if (next != null) next.drinkWater(n); 
} 

Ce que j'essaie de faire maintenant, c'est de créer une «liste chaînée» d'animaux, chacun d'entre eux buvant de l'eau en séquence. Cependant, si un chat boit n quantité d'eau, il passe n + 1 quantité d'eau à son.next

Mon but est de trouver une solution pour surmonter le problème qui «ne touche pas l'emballage original de l'animal , mais changez le comportement de l'eau potable chacun d'eux '. Je suis venu avec cette solution naïve « célèbre » avec une classe:

class InvokeStaticTypeBDrink { 
    static void typeBdrink(Animal animal, int n) { 
    animal.amount -= n; 
    if (animal.amount < 0) animal.amount = 0; 
    if (animal.next != null) { 
     if (animal instanceof Cat) 
     InvokeStaticTypeDrink.drinkWater(animal.next, n+1); 
     else if (animal instanceof Dog) 
     InvokeStaticTypeDrink.drinkWater(animal.next, n-1); 
     else 
     InvokeStaticTypeDrink.drinkWater(animal.next, n); 
    } 
    } 
} 

Ensuite, j'ai commencé à la recherche. Parce que cela a vraiment l'air solution rapide et sale. Donc, j'ai trouvé ce modèle de conception appelé «Modèle de visiteur». Eh bien, un motif assez cool qui résout le problème en double dispatch, mais il y a un problème de mon côté: l'interface Visitable (qui déclare la méthode accept()) devrait être "implémentée" par les Animals originaux. Cependant, mon but est de "NE PAS faire de modification sur l'emballage original de l'animal, mais de changer le comportement de l'eau potable". Je suis sûr qu'il me manque quelque chose. Donc, pensez-vous qu'avec un peu de hack, Visitor Pattern fonctionnerait toujours ou un autre pattern/solution serait mieux? Merci.

Répondre

2

Si vous ne voulez pas toucher les classes d'origine, la seule façon d'appliquer un modèle de visiteur consiste à envelopper les classes d'origine dans les nouvelles classes (wrapper).

Quoi qu'il en soit, si vous voulez juste changer le comportement de certains animaux, puis dans votre situation, je voudrais juste étendre ces classes spécifiques et remplacer le comportement potable.

alors vous avez un chat comme celui-ci:

class NonThirstyCat extends Cat { 
    Cat(int amount, Animal next) { 
    super(amount, next); 
    } 

    @Override 
    public void drinkWater(int n) { 
    amount += n; 
    if (amount < 0) amount = 0; 
    if (next != null) next.drinkWater(n); 
    } 
} 
0

Je suppose que subclassing ne sera pas utile dans votre cas.

Le modèle de visiteur serait bon mais il ne fonctionne pas sans modifier Animal. J'ai deux suggestions. En fait, j'en ai trois:

  1. Ne le faites pas. Repensez votre problème. Cela ressemble à un mauvais design et rompt propablement tous les principes de la POO.
  2. Utilisez AOP. Google pour AspectJ.

Or (3) essayer quelque chose comme ceci:

class FixedAnimal extends Animal { 
    public static Animal fix(Animal a) { 
     Animal result = a; 
     if (a instanceof Cat || a instanceof Dog) 
      result = new FixedAnimal(a); 
     if (a.next != null) a.next = fix(a.next); 
     return result; 
    } 
    Animal a; 
    FixedAnimal(Animal a) { 
     super(0, null); 
     this.a = a; 
    } 
    public void drink(int n) { 
     // do stuff 
     if (a.next != null) a.next.drink(n); 
    } 
} 

Bien sûr, cela fait quelques hypothèses sur l'utilisation de Animal, mais peut-être que vous avez l'idée.

Ma recommandation serait # 1. Ou soyez plus précis sur ce que vous voulez réaliser.

Questions connexes