Ein Pattern für die wiederherstellung von Daten (Undo/Restore)
Wofür ist das Memento Design Pattern notwendig?
Das Memento Design Muster ist nützlich, wenn Daten temporär vorgehalten werden sollen und je nach den Bedürfnissen des Benutzers, die alten Daten wieder abrufen werden wollen.
Als Beispiel nehmen ich ein Formular (WinFom wg. einfacher zur Darstellung) mit ein paar Kontrollen. Im Form Load-Ereignis werden die Daten geladen. Jetzt kann der Benutzer das Fomrular aktualisieren oder wiederherstellen.
Jetzt das Problem, wenn das Formular aktualisiert wurde soll die Möglichkeit bestehen die Daten wieder her zu stellen, aber wie?
Nun kommt unser Memento Design Pattern ins Spiel.
Schauen wir uns das ganze einmal an.
Bei der Erstellung des Personobjektes wird ein Duplikat der Daten in einem MomentSnapshot des Objektes Festghalten (Momento) dies wird für unsere Undo Funktionalität.
Wenn der Anwender die Updatefunktion ruft kann das Objekt z.B. in der Datenbank wieder hergestellt werden, wir haben aber über unser Personobjekt die Möglichkeit die ursprünglichen Daten wiederherstellen.
Im Memento-Pattern halten wir ein Duplikat des ursprünglichen Objekts und alle Änderungen werden in das ursprüngliche Objekt geschrieben Wenn wir die alten Daten wiederhergestellt haben müssen, können wir es wieder aus dem Replikat-Objekt holen.
Problem gelöst.
Die Umsetzung?
Zur technischen Umsetzung. Wir haben festgestellt, dass wir eine Kopie des ursprünglichen Objekts benötigen. Also legen wir uns eine kleine Klasse für die Person an.
using System;
namespace MementoDesignPattern
{
class Pattern
{
public class Person
{
public String Name { get; set; }
public String Vorname { get; set; }
MomentoPerson objMPerson = null;
public Person()
{
Name = "Grünthal";
Vorname = "Gerrit";
objMPerson = new MomentoPerson(Name, Vorname);
}
public void Update(String name, string vorname)
{
Name = name;
Vorname = vorname;
}
public void Revert()
{
Name = objMPerson.Name;
Vorname = objMPerson.Vorname;
}
}
public class MomentoPerson
{
public String Name { get; set; }
public string Vorname { get; set; }
public MomentoPerson(String name, String vorname)
{
Name = name;
Vorname = vorname;
}
}
}
}
Zusätzlich zur Person legen wir uns eine Replikatsklasse an, in der wir die Daten aus der Person ablegen können. Hier liegen die Daten für unsere Wiederherstellungsfunktion.
using System;
using System.Windows.Forms;
namespace MementoDesignPattern
{
public partial class WmbPatternMomento : Form
{
string strOut = "{0}: \nName:{1} \nVorname:{2}";
public WmbPatternMomento()
{
InitializeComponent();
}
Pattern.Person currenPerson = new Pattern.Person();
public void DisplayCustomer()
{
txtName.Text = currenPerson.Name;
txtVorname.Text = currenPerson.Vorname;
}
private void CancelClick(object sender, EventArgs e)
{
currenPerson.Revert();
DisplayCustomer();
SetUpdateInfo(string.Format(strOut, "Revert", currenPerson.Name, currenPerson.Vorname));
}
private void UpdateClick(object sender, EventArgs e)
{
currenPerson.Update(txtName.Text, txtVorname.Text);
SetUpdateInfo(string.Format(strOut, "Save", txtName.Text, txtVorname.Text));
}
private void SetUpdateInfo(string infoText)
{
lblUpdate.Text = infoText;// string.Format(strUpdate, txtName.Text, txtVorname.Text);
}
private void WmbPatternMomentoLoad(object sender, EventArgs e)
{
DisplayCustomer();
}
}
}
using System;
using System.Windows.Forms;
namespace MementoDesignPattern
{
public partial class WmbPatternMomento : Form
{
string strOut = "{0}: \nName:{1} \nVorname:{2}";
public WmbPatternMomento()
{
InitializeComponent();
}
Pattern.Person currenPerson = new Pattern.Person();
public void DisplayCustomer()
{
txtName.Text = currenPerson.Name;
txtVorname.Text = currenPerson.Vorname;
}
private void CancelClick(object sender, EventArgs e)
{
currenPerson.Revert();
DisplayCustomer();
SetUpdateInfo(string.Format(strOut, "Revert", currenPerson.Name, currenPerson.Vorname));
}
private void UpdateClick(object sender, EventArgs e)
{
currenPerson.Update(txtName.Text, txtVorname.Text);
SetUpdateInfo(string.Format(strOut, "Save", txtName.Text, txtVorname.Text));
}
private void SetUpdateInfo(string infoText)
{
lblUpdate.Text = infoText;
}
private void WmbPatternMomentoLoad(object sender, EventArgs e)
{
DisplayCustomer();
}
}
}
Und so Sieht es aus: