Sto creando un semplice framework di sviluppo di giochi con Ruby.
C'è un sistema di nodi. Un nodo è un'entità di gioco e ha una posizione. Può avere nodi figli (e un nodo genitore). I bambini sono sempre disegnati relativamente ai loro genitori.
I nodi hanno un campo @position
. Chiunque può modificarlo. Quando tale posizione viene modificata, il nodo deve aggiornare i suoi figli di conseguenza per disegnarli correttamente relativamente ad esso.
@position
contiene un'istanza Point
(una classe con proprietà x e y, più alcuni altri metodi utili).
Devo sapere quando cambia lo stato di @position
di un nodo, quindi posso dire al nodo di aggiornare i suoi figli.
Questo è facile se il programmatore fa qualcosa del genere:
@node.position = Point.new(300,300)
Perché è equivalente a chiamare questo:
# Code in the Node class
def position=(newValue)
@position = newValue
update_my_children # <--- I know that the position changed
end
Ma mi sono perso quando questo accade:
@node.position.x = 300
L'unico che conosce che la posizione modificata è l'istanza Point
memorizzata nella proprietà @position
del nodo. Ma ho bisogno che il nodo sia avvisato!
È stato a questo punto che ho considerato il pattern Observer . Fondamentalmente, Point
è ora osservabile.
Quando a una proprietà position
di un nodo viene assegnata una nuova istanza Point
(tramite l'operatore di assegnazione), smetterà di osservare il Point
precedente (se presente) e inizia a osservare quello nuovo. Quando un'istanza Point
ottiene una modifica di stato, verranno notificati tutti gli osservatori (il nodo che lo possiede), quindi ora il mio nodo può aggiornare i suoi figli quando la posizione cambia.
Un problema è quando questo accade:
@someNode.position = @anotherNode.position
Ciò significa che due nodi stanno osservando lo stesso punto. Se cambio una delle posizioni del nodo, anche l'altra cambierebbe. Per risolvere questo problema, quando viene assegnata una posizione, ho intenzione di creare una nuova istanza Punto, copiare% s_dec% e% co_de dell'argomento passato e memorizzare il mio punto appena creato invece di memorizzare quello passato.
Un altro problema che temo è questo:
somePoint = @node.position
somePoint.x = 500
Questo, tecnicamente, modificerebbe la posizione di x
. Non sono sicuro che qualcuno si aspetterebbe un comportamento tale . Ho l'impressione che le persone vedano y
come una specie di primitivo piuttosto che un oggetto reale.
Questo approccio è anche ragionevole? Motivi per cui mi sento scettico:
- Ho sentito che il pattern Observer dovrebbe essere usato con, beh, molti osservatori. Tecnicamente, in questo scenario c'è un solo osservatore alla volta.
- Quando assegni la posizione di un nodo come un'altra (
@node
), dove creo un'intera nuova istanza piuttosto che archiviare il punto passato, ci si sente in forma o addirittura inefficiente.