2013-04-24 11 views
5

Ich arbeite an einem Projekt für die Universität, wo wir ein Spiel programmieren. In diesem Spiel können mehrere Effekte auftreten und ein Effekt kann beeinflussen, wie sich ein anderer Effekt verhält. Jetzt war einer der Idee, ein zusammengesetztes Muster zu verwenden, das zuerst wie eine feste Lösung schien. Das größte Problem hierbei ist, dass die Art und Weise, wie sich ein Effekt verhält, davon abhängt, mit welchem ​​Effekt er gekoppelt ist und die einzige Möglichkeit, dies zu beheben, war die Verwendung von .getClass() oder einer Instanz, die wir um jeden Preis vermeiden wollen.Vermeiden Sie instanceof in einem zusammengesetzten Muster

Wie können Sie dieses Problem beheben?

Edit (ein kleines Beispiel): Ich habe kein explizites Code-Beispiel, aber ich werde versuchen, ein bisschen mit dem folgende Beispiel zu verdeutlichen:

Also das Spiel hat Granaten (die natürlich explodieren können und verursachen, wird diese Explosion als "Explosionseffekt" angesehen. Das Quadrat, auf dem die Granate positioniert ist, kann zur Laufzeit einen Stromausfall haben (PowerfailureEffect). Der Explosionseffekt und der Energieausfalleffekt können gekoppelt werden, wodurch die Explosion stärker wird und mehr Schaden verursacht. Der Explosionseffekt kann auch mit anderen Effekten gekoppelt sein, die bewirken, dass sich der Explosionsschaden noch anders verhält.

+4

Ein Codebeispiel würde es einfacher machen, Ihre Frage zu beantworten. –

Antwort

2

Sie könnten das Visitor Design Pattern verwenden. Alle Effektklassen implementieren eine Effektschnittstelle. Die Hauptklasse fragt die EffectB-Klasse mit der Effect-Interface-Methode, wie sie sich verhalten soll. Die Implementierung der Effect-Methode in der EffectB-Klasse ruft die richtige Methode in der Hauptklasse auf.

-1

Ein gebräuchliches Anti-Pattern verwendet eine Typprüfung, zum Beispiel mit instanceof anstelle von Polymorphie. Hier ist ein einfaches Beispiel.

public class Shape { 
    public void draw() { 
     if (this instanceof Square) { 
      // Draw a square 
     } else if (this instanceof Circle) { 
      // Draw a circle 
     } 
    } 
} 

public class Square extends Shape { 
    // ... 
} 

public class Circle extends Shape { 
    // ... 
} 

Beachten Sie, dass in der draw() Methode in der Klasse Shape, bestimmen wir, was in der Art des aktuellen Objekts suchen zu ziehen, und dann den entsprechenden Code ausgeführt wird. Dies hat mehrere Nachteile: Die Klasse Shape muss über alle Unterklassen wissen, und wenn Sie eine neue Form hinzufügen möchten, müssen Sie auch die Klasse Shape ändern. Es ist viel besser Polymorphismus zu verwenden, durch Überschreiben der draw() Methode in den Unterklassen:

public abstract class Shape { 
    public abstract void draw(); 
} 

public class Square extends Shape { 
    public void draw() { 
     // Draw a square 
    } 
} 

public class Circle extends Shape { 
    public void draw() { 
     // Draw a circle 
    } 
} 

diese Weise Klasse Shape nicht wissen muss, über alle ihre Unterklassen, brauchen Sie nicht Shape zu ändern a hinzufügen neue Form und alle Logik, die zu einer bestimmten Form gehört, sind an der Stelle, wo sie hingehört (die Klasse für diese Form).

+0

Downvoter, bitte erkläre, warum du abgelehnt hast. – Jesper

+0

Ich habe nicht downvote, aber ich erwarte, dass der Downvoter Ihre Antwort nicht vollständig gelesen hat. Die erste Hälfte Ihrer Antwort scheint zu implizieren, dass Sie die Verwendung von "instanceof" vorschlagen, die zweite Hälfte erklärt die Nachteile und Polymorphismus als eine Alternative. Ich denke jedoch, dass ein bestimmter Kontext, wie dies auf ein zusammengesetztes Muster angewendet werden kann, dieser Antwort Tiefe verleihen würde. – seanhodges

1

Wie wäre es mit einer anderen Schnittstelle? Vielleicht haben verschiedene Modifier Schnittstellen, die die Effekte implementieren. Diese Modifikatoren könnten Dinge wie "erhöhenExplosivePower" tun. Sie können instanceof tun, um zu sehen, ob die Klasse den Modifikator implementiert, und dann kann ein Effekt den anderen modifizieren.

Hinweis: tun eine instanceof auf einer Schnittstelle ist durchaus akzeptabel - Sie arbeiten nicht aus, wenn es etwas tun kann, basierend auf was es ist, aber auf welche APIs es hat.

0
public void test(){ 
    methodForWaterEffect(new WaterEffect()); 
    combinationAttack1(new FireEffect(), new WaterEffect()); 
} 

interface Effect{ 
    public void activateEffect(); 
} 

class FireEffect implements Effect{ 

    @Override 
    public void activateEffect() { 
     System.out.println("Fire!"); 
    } 

} 

class WaterEffect implements Effect{ 

    @Override 
    public void activateEffect() { 
     System.out.println("Water!"); 
    } 

} 
public void combinationAttack1(FireEffect fe, WaterEffect we){ 
    //your algorithm here 

} 

public void methodForWaterEffect(WaterEffect fe){ 
    fe.activateEffect(); 
} 

Ich habe einen sehr einfachen Vorschlag. Warum nicht Klassen für jeden Effekt erstellen, der eine Schnittstelle namens Effekt implementiert? Wenn Sie versuchen, Kombinationsangriffe zu simulieren, warum sollten Sie nicht für jeden dieser Kombinationsangriffe Funktionen entwickeln?

in Ihrem Beispiel Also, es geht

public void combination2(PoisonEffect pe, PowerFailureEffect pf){ 

} 

Dies könnte scheint Belastung der Arbeit sein, aber ich denke, das ist sehr gut Code abkoppelt und später können Sie es einfacher finden, um Ihren Code zu verwalten.

Bitte beachten Sie, dass sie zur Vereinfachung nicht in separaten Klassendateien enthalten sind = D.

Verwandte Themen