OOP: passare un nuovo oggetto come parametro o crearlo all'interno del costruttore?

5

Ho tre sottoclassi che ereditano da Hero :

  • Warrior
  • Magician
  • Amazon

I tre hanno un Weapon , che è sempre lo stesso:

  • Warrior contiene sempre un Sword (che eredita da Weapon )
  • Magician contiene sempre un Wand (che eredita da Weapon )
  • Amazon contiene sempre un Bow (che eredita da Weapon )

Ho in mente diverse soluzioni, come:

  1. Passare l'arma come parametro del costruttore (questo dovrebbe essere fatto da una Factory? In questo caso, quando si crea un Warrior dovrebbe venire già con un Sword , e così via ... )

  2. Creazione dell'arma specifica all'interno del costruttore per ognuno dei Heroes .

Pensando a ulteriori test, soluzione 1 mi consentirà di passare una percentuale fittizia Weapon durante la creazione dell'oggetto. D'altra parte, la soluzione 2 non lo farà, e suppongo che non rispetterò i principi del test unitario isolando l'unità (il mio Hero ) da altri componenti (il Weapon ) .

Che cosa pensi qui?

    
posta charliebrownie 05.03.2017 - 04:35
fonte

5 risposte

5

Soluzione 3: consenti a ogni eroe di costruire senza un'arma. Invece, dai al tuo eroe una proprietà pubblica per l'arma che detiene e assegna questa proprietà dall'esterno ogni volta che è necessario, o riassegnala in seguito. Questa proprietà potrebbe essere null , a indicare che l'eroe non possiede un'arma.

Quando si creano classi di entità come una classe "eroe", eviterei di implementare qualsiasi cosa delle specifiche meccaniche di gioco all'interno degli oggetti. Quando, dove e come le armi vengono create e passate intorno a è parte di quella meccanica, quindi ti consiglio di non codificarle in alcuno degli oggetti.

    
risposta data 05.03.2017 - 07:55
fonte
3

Hai ragione quando dici che la soluzione 2 non ti permetterà di prendere in giro le armi, il che ostacola i test. h Un altro svantaggio della soluzione 2 è che creerebbe un accoppiamento tra due classi concrete, che non è buono .

L'attivazione di un'arma all'interno del costruttore rende la relazione tra Hero e Weapon una delle composizione , che non modella il domina tutto questo bene, poiché le armi non fanno parte degli eroi, le armi possono esistere indipendentemente dagli eroi e viceversa. Tutti abbiamo visto film in cui un'arma mytical giace dormiente o rimane nascosto fino a quando un eroe perticolare è destinato a "attivarlo" o a trovarlo, o un impostore riesce a rubarlo ( spada sulla roccia , ecc.), così le armi possono esistere separatelly dagli eroi. Inoltre, il più delle volte, gli eroi hanno le loro armi fatte per loro, ad esempio il dio greco Efesto era il fabbro per gli dei e hanno creato armi per loro, quindi la creazione di armi non dovrebbe avvenire nel costruttore dell'eroe. Inoltre, quando un eroe viene ucciso, l'arma rimane. Pertanto, la relazione dovrebbe essere aggregazione .

Quindi, l'opzione 2 IMHO è un no-go e la soluzione 1 è la strada da percorrere.

    
risposta data 05.03.2017 - 04:52
fonte
2

La distinzione di cui parli è tra aggregazione e composizione .

Usa la composizione quando la durata delle parti è uguale alla durata della classe contenente. Una mano è una parte composita di un essere umano, sarebbe normale costruire le parti composite all'interno della classe o il costruttore del tutto. Utilizzare l'approccio che riflette più accuratamente l'utilizzo.

Viceversa Farina e Uova sono usate per fare in modo che una Torta esistano prima, quindi passale al Costruttore della Torta. Le mani crescono con la persona, quindi costruiscile all'interno della classe. Una semplice regola empirica è se X è parte di Y quindi applica la composizione.

Utilizzare l'aggregazione quando la durata delle parti non è limitata dalla durata del contenitore. Un'arma ha una vita diversa per una persona, può essere cambiata, viene raccolta e può essere eliminata. È costruito da un fabbro d'armi e dato, venduto, trovato dall'eroe. Una semplice regola empirica per l'aggregazione è, se X è usato (o qualsiasi verbo specifico) di Y quindi applicare l'aggregazione.

Class Character {
  Hand right = new Hand();
  Hand left;

  Character() {
    left = new Hand();
    }

  public equipLeft(Weapon weapon) {
    left.equipped(weapon)
    }
  }
    
risposta data 05.03.2017 - 08:18
fonte
0

Un'altra buona domanda quando si pensa a questo: è questo 1: 1 o 1: molti? In altre parole, un Eroe può portare 0 o più armi? Probabilmente sì, giusto? Persino il mio arciere D & D che non ha mai maltrattato porta anche una spada opaca arrugginita. Quindi passare esattamente un'arma in un costruttore, o automaticamente crearne uno, sono entrambi sbagliati. Come suggerito da @Doc Brown, dovresti avere un metodo addWeapon() . E probabilmente anche un removeWeapon() .

    
risposta data 06.03.2017 - 08:13
fonte
-1

L'eroe dovrebbe creare la propria arma internamente perché hai dichiarato che ognuno avrà sempre lo stesso tipo di eroe. L'arma è come un braccio (o una gamba), è solo una parte inseparabile dell'eroe. Quindi non distrarti testando i dogmi e lascia che il tuo modello sia rovinato da loro. È impensabile che un guerriero finisca con una bacchetta nelle sue mani, quindi non dovresti facilitarla. Si potrebbe anche dire che l'intero albero delle armi non ha senso perché la flessibilità di lanciare armi diverse tra gli eroi non è necessaria o desiderata. Basta integrare l'arma specifica dell'eroe nell'eroe.

    
risposta data 05.03.2017 - 08:55
fonte