an object that you keep to remember a person, place, or event
Yazılım dünyasında Memento örüntüsü, bir nesnenin iç verisini bilmeden, nesnenin belli bir andaki halini saklayabilmemiz sağlar. Böylece istenilen bir anda, geriye dönebiliriz. Bu tasarım örüntüsü undo veya rollback işlemlerinde kullanılır.
Undo Framework
QT Undo Framework için Memento yerine Command örüntüsünü kullanmış. Memento sınıfı yerine QUndoCommand, Caretaker sınıfı yerine QUndoStack nesnesi kullanılmış.
Örüntüdeki nesneler ve görevleri
- Originator undo veya restore edilmesi gereken domain nesnedir. Memento parametresi alan save() ve restore() metodları sunar.
- Memento ise Originator'ın verisini saklar.
- Caretaker nesnesi Memento'ların listesini saklar.
Bazı notlar şöyle
Java- We can make Memento Design Pattern implementation more generic by using Serialization; that will eliminate the requirement of every class having its own Memento class.- The Memento Design Pattern can also be used with the Command Design Pattern for achieving undo of the commands.
Örnek
Originator şöyle tanımlanır
public class Employee {...public EmployeeMemento createMemento() {return new EmployeeMemento(empId, name, designation, salary, department, project);}public void restore(EmployeeMemento memento) {this.empId = memento.empId;...}}
Memento nesnesi sadece veriyi saklar
public class EmployeeMemento {...public EmployeeMemento(int empId, String name, String designation, long salary,...) {...}}
Caretake sadece Memento listelerini saklarr
public class EmployeeCaretaker {protected Map<Integer, Map<String, EmployeeMemento>> mementoHistory = ...;public void addMemento(int empId, String mementoMessage, EmployeeMemento memento) {...}public EmployeeMemento getMemento(int empId, String mementoMessage) {...}}
Kullanmak için şöyle yaparız
public static void main(String[] args) {EmployeeCaretaker caretaker = ...Employee rachel = ...Employee michael = ...//SaveEmployeeMemento rachelMemento = rachel.createMemento();EmployeeMemento michaelMemento = michael.createMemento();caretaker.addMemento(racheal.getEmpId(), "...", rachelMemento);caretaker.addMementomichael.getEmpId(), "...", michaelMemento);//Update domain objectsrachel .setDesignation("Manager").setSalary(120000);michael.setProject("Android App");//Get saved snapshotsrachelMemento = caretaker.getMemento(rachel.getEmpId(),"...");michaelMemento = caretaker.getMemento(micheal.getEmpId(), "...");//Restorerachel.restore(rachelMemento);michael.restore(michaelMemento);}
Örnek
Bir projede her Originator için farklı bir Memento sınıfı yazmak yerine şöyle yaptım. Böylece her Originator'a createMemento(), restoreMemento() gibi bir şey yazmaya da gerek kalmadı. Her takeSpanshot() işleminde Memento nesnesi bir isim listede saklandı.
Memento memento = new Memento();try(ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);GZIPOutputStream zos = new GZIPOutputStream(baos);ObjectOutputStream os = new ObjectOutputStream (zos);) {foo.serialize(os);bar.seriazlie(os);os.close();memento.setData(baos.toByteArray();}try(ByteArrayInputStream bais = new ByteArrayInputStream (memento.getData());GZIPInputStream zis = new GZIPInputStream(bais);ObjectInputStream is = new ObjectInputStream (zis);) {Foo foo = (Foo)is.readObject();Bar bar = (Bar)is.readObject();}
Örnek
public class Originator {
private String state;
private Integer code;
private Map<String, String> parameters;
public Memento save() {
return new Memento(this);
}
public void restore(Memento memento) {
this.state = memento.getState();
this.code = memento.getCode();
this.parameters = memento.getParameters();
}
/**
* We use Memento class for making a snapshot of Originator state.
*/
public class Memento {
private String state;
private Integer code;
private Map<String, String> parameters;
public Memento(Originator o) {
Cloner cloner = new Cloner();
this.state = cloner.deepClone(o.state);
this.code = cloner.deepClone(o.code);
this.parameters = cloner.deepClone(o.parameters);
}
}
}
Caretaker basit bir liste sınıfıdır.public class Caretaker {
List<Originator.Memento> snapshots;
public Caretaker() {
this.snapshots = new ArrayList<Originator.Memento>();
}
public void addSnapshot(Originator.Memento memento) {
snapshots.add(memento);
}
public Originator.Memento find(Criteria criteria, Object key) {
//...
}
}
Tüm örüntünün kullanılmasıOriginator originator = new Originator();
//Save with Memento the state of Originator
Caretaker caretaker = new Caretaker();
caretaker.addSnapshot(originator.save());
//Search with Caretaker
Originator.Memento m = caretaker.find(Criteria.ByCode, 500);
//Restore originator
originator.restore(m);
Hiç yorum yok:
Yorum Gönder