2013-04-24 13 views
5

Sto lavorando a un progetto per l'università in cui stiamo programmando un gioco. In questo gioco possono verificarsi diversi effetti e un effetto può influenzare il comportamento di un altro effetto. Ora una delle idee stava usando un modello composito che all'inizio sembrava una soluzione solida. Il problema più grande qui è che il modo in cui un effetto si comporta dipende dall'effetto con cui è accoppiato e l'unico modo in cui abbiamo visto risolvere questo problema era usare .getClass() o l'istanza di cui vogliamo evitare a tutti i costi.Evitare l'istanza di un modello composito

Quali sono alcuni modi per progettare questo problema?

Edit (un piccolo esempio): Non ho un esempio di codice esplicito ma cercherò di chiarire un po 'con il seguente esempio:

Così il gioco ha granate (che può ovviamente esplodere e causare danni), questa esplosione è vista come un "ExplosionEffect". Il quadrato su cui è posizionata la granata può avere un powerfailure in fase di esecuzione (PowerfailureEffect). ExplosionEffect e PowerfailureEffect possono essere accoppiati e questo fa sì che l'esplosione sia più forte e causi più danni. ExplosionEffect può anche essere associato ad altri effetti che causano un comportamento ancora più diverso del danno da esplosione

+4

Un esempio di codice renderebbe più semplice rispondere alla domanda. –

risposta

2

È possibile utilizzare il modello di progettazione del visitatore. Tutte le classi di effetti implementano un'interfaccia Effect. Classe principale chiedi alla classe EffectB usando il metodo dell'interfaccia Effect come dovrebbe comportarsi. L'implementazione del metodo Effect nella classe EffectB chiama il metodo giusto nella classe principale.

-1

Un anti-pattern comune utilizza il controllo del tipo, ad esempio con instanceof, anziché il polimorfismo. Ecco un semplice esempio.

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 { 
    // ... 
} 

Si noti che nel metodo draw() in classe Shape, determiniamo cosa disegnare guardando il tipo dell'oggetto corrente, e quindi l'esecuzione il codice appropriato. Questo ha diversi svantaggi: la classe Shape deve conoscere tutte le sue sottoclassi e se si desidera aggiungere una nuova forma, è necessario modificare anche la classe Shape. E 'molto meglio usare il polimorfismo, sovrascrivendo il metodo draw() nelle sottoclassi:

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 
    } 
} 

In questo modo, la classe Shape non ha bisogno di conoscere tutte le sue sottoclassi, non è necessario modificare Shape per aggiungere un nuova forma e tutta la logica che appartiene a una particolare forma è nel luogo in cui appartiene (la classe per quella forma).

+0

Downvoter, per favore spiega perché hai downvoted. – Jesper

+0

Non ho fatto un downvote, ma mi aspetto che il down-voter non abbia letto completamente la risposta. La prima metà della tua risposta sembra implicare che stai suggerendo l'uso di 'instanceof', la seconda metà spiega gli svantaggi e il polimorfismo come alternativa. Tuttavia, penso che un certo contesto di come questo possa essere applicato a un pattern composito aggiungerebbe profondità a questa risposta. – seanhodges

1

Come su un'altra interfaccia. Forse hanno varie interfacce Modifier implementate dagli effetti. Questi modificatori potrebbero fare cose come "increase ExplosivePower". Puoi fare instanceof per vedere se la classe implementa il modificatore e quindi un effetto può modificare l'altro.

Nota: eseguire un'interfaccia instanceof su un'interfaccia è abbastanza accettabile: non si sta lavorando se si può fare qualcosa in base a ciò che è ma su quali API ha.

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(); 
} 

Ho un semplice suggerimento. Perché non creare classi per ogni effetto che implementa un'interfaccia chiamata Effetto. Inoltre, se stai cercando di simulare attacchi combinati, perché non creare funzioni per ciascuno di questi attacchi combinati?

Quindi nel tuo esempio, che sta per essere

public void combination2(PoisonEffect pe, PowerFailureEffect pf){ 

} 

Questo potrebbe sembra carico di lavoro, ma penso che questo disaccoppia il codice molto bene e poi si potrebbe trovare più facile per gestire il vostro codice.

Si prega di notare che per la semplicità, non sono in file di classe separati = D.

Problemi correlati