2010-09-30 17 views
7

Se sto programmando un gioco in cui c'è un lavoratore che taglia il legno (dagli alberi), dove inserirò il metodo "cutWood", nella classe worker o nella classe tree?Problema di progettazione orientata agli oggetti

MODIFICA: Il primo esempio che ho letto su OOD riguardava un cerchio (una classe chiamata cerchio) che contiene un metodo chiamato "area di calcolo". Ora, un cerchio abbastanza sicuro non calcola la propria area. L'unico modo per pensarci è che l'area di calcolo è un'operazione pertinente al cerchio (un'operazione eseguita sul cerchio)

Quindi, il metodo cutWood è rilevante sia per l'operatore che per l'albero.

+1

chi taglia il legno? – Cristian

+0

Chi ha tagliato il formaggio! – Secko

+0

Una cerchia non calcola la propria area? Hmmm. Penso che tu abbia erroneamente interpretato l'esempio: facendo qualcosa per cui nessun altro oggetto è necessario, e per il quale la classe ha più conoscenza (cioè il raggio), è ESATTAMENTE quello che dovrebbe andare in una classe. Dove si può discutere di cose come circle.draw (ScreenObject) - una classe autonoma dovrebbe conoscere i dettagli di un particolare sistema grafico? –

risposta

4

Chiedetevi: i lavoratori tagliano il legno o fanno tagliare gli alberi?

+2

Ma l'albero si taglia , potrebbe essere CutMe (Worker whichWorker), che potrebbe dire se l'albero avesse abbastanza legno da tagliare. - Sì, il lavoratore dovrebbe tagliare l'albero – PostMan

+1

Se lo stato interno dell'albero ha bisogno di sapere chi lo ha tagliato e se è stato tagliato o meno, allora il metodo cutesato Workers chiamerebbe i metodi che l'albero espone per aggiornare il suo stato. – codelark

+0

E Worker estende WoodChuck o viceversa? : p –

4

Alla tua domanda hai praticamente risposto: "un lavoratore che taglia legna". Dovresti metterlo alla classe operaia.

+0

E se poi vuoi che anche il lavoratore vada a lavorare, cuocia il pane, aggiusti le macchine, la pentola del fumo, qualunque cosa. Quel lavoratore diventerà un oggetto divino. –

+0

@ Mark H: Non ti capisco proprio qui. Un oggetto divino è un oggetto che ha troppa responsabilità. Questo artigiano non aggiusterà mai le macchine né cuocerà il pane. Il lavoratore avrà probabilmente più metodi, ad esempio takePause(), ma fintanto che questi sono correlati all'obiettivo primario del lavoratore, non c'è alcun problema. –

+0

Hai ipotizzato che il lavoratore non aggiusterà mai le auto, ma non lo sai, oppure non sai se cambierà in futuro. Se la responsabilità del lavoratore cambia, sarà il gonfiore del suo oggetto. Tuttavia, non importa se la responsabilità di un lavoratore cambia, tagliare un albero agirà sempre su un albero - e quindi dovrebbe essere parte dell'albero. In ogni caso, non ci sono davvero molte possibilità che un albero cambi le responsabilità. –

0

Poiché un singolo operatore può tagliare più di un albero, sembra più probabile che si desideri inserire cutWood() nella classe worker.

3

Creare un metodo

cut(Material m)

per il lavoratore per oggetto-orientedness supplementare.

+5

A meno che il lavoratore non tagli qualcos'altro, questo sarebbe un buon esempio di eccessiva astrazione ;-) – codelark

+1

// TODO: inserire EmoWorker scherzo – STW

+0

@codelark Se la descrizione dice boscaiolo, sono d'accordo, ma un lavoratore può significare qualsiasi cosa/sarcasmo – Hans

1

È possibile avere un metodo cutWood nella classe worker e un metodo cutted nella classe tree. Ovviamente, worker.cutWood chiama tree.cutted, che potrebbe restituire la quantità di legno raccolto. tree.cutted farebbe tutto il necessario per far morire l'albero.

Se si considerano le chiamate di metodo come "messaggi inviati da un oggetto a un altro", ha molto più senso dire "il giocatore invia un messaggio" taglia legna "al lavoratore che a sua volta invia un messaggio" taglia " all'albero ".

2

devi modificare l'albero mentre viene tagliato?

devi modificare l'operatore mentre taglia un albero?

posso immaginare che ci si finisce con un servizio di WoodCutting, che gestisce l'evento, eventualmente, modifiche ad entrambi, o, a sua volta chiama worker.cutWood() E tree.woodCut()

ahah che domanda;)

8

non lo faccio vedere qualsiasi coesione per avere un metodo di taglio del legno nel lavoratore. Il taglio è fatto sull'albero e dovrebbe quindi essere parte della classe dell'albero. Presumibilmente, il taglio del legno comporterà anche il cambiamento dello stato interno della classe del legno.

Un operatore deve chiamare il metodo di taglio su qualsiasi albero desideri, piuttosto che l'albero che dice al lavoratore che deve tagliarlo. Se vuoi astrarre questo come Hans ha suggerito, potresti creare un'interfaccia ICuttable per il metodo Cut e farlo implementare dal tuo albero.

Considera qualcosa che ti è familiare, un String. Quando si desidera tagliare una stringa (divisa), non si definisce un metodo splitString in ogni oggetto che sta per farlo.Qualunque oggetto decida di dividere la stringa, avviene la stessa cosa - e di solito è necessario conoscere l'interno dell'oggetto di destinazione (la stringa) per farlo. Molti altri oggetti chiamano semplicemente il metodo split della stringa. L'oggetto stringa ha un'elevata coesione - perché i metodi contribuiscono a un compito comune - manipolando le stringhe.

Non vedo come il taglio del legno contribuisca molto all'oggetto operaio stesso.

0

Il metodo non è disponibile nell'oggetto Saw?

Più seriamente, penso al target della chiamata al metodo come al "soggetto", al metodo stesso come a un "verbo" e ai suoi parametri (se il verbo è transitivo) come "oggetti diretti". Quindi, in questo esempio, sarebbe worker.cut(tree).

2

Suona come un candidato per il modello di strategia per me. Potrebbe essere necessaria una classe astratta WorkerAction con un metodo performAction. Quindi le sottoclassi della classe WorkerAction implementeranno i dettagli come tagliare un albero, scavare per l'oro e altre azioni dei lavoratori. Quindi la sottoclasse conosce i dettagli dell'albero e può chiamare i metodi necessari sull'albero per influenzare l'albero mentre viene tagliato.

La classe worker ha quindi solo bisogno di un riferimento a un'istanza di una WorkerAction concreta su cui chiama performAction(). L'operatore non conosce i dettagli dell'albero o dell'oro ecc. In questo modo l'operatore può eseguire l'azione ma non limita il lavoratore a una sola azione. In effetti non è più necessario modificare la classe worker se si desidera che il lavoratore faccia più azioni in futuro.

+0

Sono d'accordo che questo è l'approccio da usare - ma la mia opinione sarebbe diversa per le responsabilità delle sottoclassi di WorkerAction. Dire una classe TreeCuttingAction, vorrei semplicemente che il metodo performAction chiamasse un metodo .cut dell'albero (per i motivi indicati nella mia risposta precedente) - TreeCuttingAction non conosce necessariamente i dettagli dell'albero che sta tagliando - solo che lui lo sta tagliando. –

+0

@Mark H Hmm. Sembra che abbia semplicemente spinto la decisione in un diverso livello di astrazione qui senza effettivamente rispondere alla domanda. Penso tuttavia che sia d'accordo con la tua risposta sul fatto che i dettagli di tagliare l'albero debbano risiedere nell'albero. Quindi sì. PerformAction dovrebbe chiamare solo cut() sull'albero. –

0

Questa domanda può davvero essere risolta solo se si spiega cosa fa cutWood.

Se cutWood agisce soltanto sullo stato di un Tree allora appartiene a Tree esempio,

public void cutWood() { 
    this.height = 0; 
} 

Nel caso di calculateArea serve solo il raggio di un cerchio (assumere pi è costante) per fare questo calcolo - nient'altro. Ecco perché appartiene a Circle.

Smettere di provare a modellare il mondo reale troppo da vicino e guardare a ciò che il tuo metodo deve effettivamente fare.

1

Il design degli oggetti consiste nell'assegnare responsabilità alle classi. Ciò significa che non c'è davvero una buona risposta a questa domanda. Poiché tutto dipende da come è il modello le responsabilità in il tuo design. (Vedi: Larman)

Così si necessità di decidere quale oggetto/classe è responsabile di che cosa. Questo ti condurrà a correggere le risposte alla domanda su dove mettere il tipo di metodi.

Quindi chiedete di essere voi stessi domande come: l'operaio decide da solo di tagliare il legno? Se lo fa, probabilmente non ha bisogno di essere ordinato così, quindi non avrà bisogno di un metodo taglio (albero). Ma se l'utente può ordinargli di farlo, avrà bisogno di un metodo taglio (albero). Un altro esempio: l'albero deve sapere che è tagliato? Bene, se un albero tagliato porta solo alla sua rimozione dalla foresta, potrebbe non avere bisogno di un tale metodo .Ma se si assegna all'albero la responsabilità di (ri) disegnarsi durante il taglio, potrebbe essere necessario un metodo tree.cut(). L'albero potrebbe anche essere modellato con una larghezza e che possa calcolare quanti tagli sono necessari prima di crollare.

0

Questo è un argomento interessante. A volte ho pensato anch'io a uno scenario simile. Penso che un buon modo per andare, è mettere il metodo in classe con la massima coesione. Quindi la classe Tree sarebbe la prima scelta. D'altro canto, se provi ad abbinare un modello del mondo reale, direi che la classe Worker deve essere in grado di eseguire alcune azioni che includono il taglio di un albero. Spesso mi trovo in questo tipo di situazioni e mi chiedo dove sia il posto giusto per mettere questo metodo. Un altro approccio sarebbe una classe che conosce il lavoratore e l'albero, e quindi gestisce il meachismo del taglio dell'albero. In questo modo entrambe le classi (albero, lavoratore) non ne saprebbero nulla.

Problemi correlati