Citation :en PHP, quand tu reviens en arrière sur un objet, tous les autres objets auxquels tu avait passé la référence de ta première copie doivent être modifiés pour pointer vers la nouvelle copie.
Ouep, la solution étant alors d'altérer l'objet existant au lieu de le remplacer (car mutable), ou alors, de faire du Proxy
Dans l'idée, une classe "ProxyChose" référence un objet "Chose" (et qui passe ses appels de méthodes à ce "Chose"), et ce "ProxyChose" est référencé par les autres objets du monde. Pour restaurer "Chose", on la récupère du "Memento" et on la passe au "ProxyChose": tous les objets qui pointaient vers "ProxyChose" pointent toujours dessus, et tous les appels de méthodes reçus par "ProxyChose" repartent vers le nouveau "Chose".
C'est vrai qu'alors, on ne change pas ce vers quoi le monde pointe (il pointe vers "ProxyChose", qui ne change pas) mais le comportement est similaire.
Oui, Memento sera plus gourmand que le clone seul, puisque le Memento, c'est "Object Memento + clone". Ce genre de considération (quantité de mémoire occupée), mieux vaut ne s'en préoccuper qu'une fois qu'on rencontre des problèmes plutôt qu'avant. Le problème, c'est que dès qu'on parle "d'optimisation", on a une image positive en tête... On devrait plutôt parler de "Radinerie de mémoire"
En PHP, le garbage collector fera le même taff: il virera le cloné s'il n'est plus référence (et le cloné ne sera plus référencé si le Memento ne l'est plus).
Note que pour les considérations mémoires, Memento présente l'avantage d'être "Flyweightable" comme le dit Max. Dans l'idée, le "Memento" peut conserver la liste des "Memento" en mémoire, regarder dans cette liste s'il existe déjà un exemplaire de l'objet à cloner, et si oui, il ne le clone pas et y fait référence.
Code PHP :
<?php
interface IMemento {
public function getCopy();
}
class Memento IMemento {
//...
}
class FlyweightMemento implements IMemento {
private static $mementos = array();
private $stored;
public function __construct($object) {
$copy = null;
foreach (static::$mementos as $memento)
if ($memento->getCopy() == $object)
$copy = $object;
if ($copy == null) {
$this->stored = clone $object;
static::$mementos[] = $this->stored;
}
else
$this->stored = $object;
}
}