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:

MomentoPatern1

Momento2

Momento3

 

Neuste Einträge

Composite Pattern

Dieses Pattern kann genutzt werden, um Baumähnliche Strukturen abzubilden.

Als Beispiel habe ich hier eine kleine Firmenstruktur implementiert.
Die Klasse des CompositePattrns

namespace CompositePattern
{
    interface IMitarbeiter
    {
        string Bezeichnung();
    }
 
    class Chef : IMitarbeiter
    {
        public virtual string Bezeichnung()
        {
            return "Ich bin der Chef und mache alles anders.";
        }
    }
 
    class Teamleiter : Chef, IMitarbeiter
    {
        public override string Bezeichnung()
        {
            return "Ich bin der 1. Honk vom Chef";
        }
    }
 
    class Teamleiter2 : Chef, IMitarbeiter
    {
        public override string Bezeichnung()
        {
            return "Ich bin der 2. Honk vom Chef";
        }
    }
 
    class Gruppenleiter : Teamleiter, IMitarbeiter
    {
        public override string Bezeichnung()
        {
            return "Ich bin der Gruppenleiter vom 1. Honk";
        }
    }
 
    class GruppenMitarbeiter : Gruppenleiter, IMitarbeiter
    {
        public new string Bezeichnung()
        {
            return "Ich bin GruppenMitarbeiter des Gruppenleiter´s vom 1. Honk und darf aufräumen.";
        }
    }
 
    
}

Und hier noch die Programmklasse

using System;
using System.Collections.Generic;
 
namespace CompositePattern
{
    class Program
    {
        static void Main(string[] args)
        {
 
            IMitarbeiter grpMitarbeiter = new GruppenMitarbeiter();
            IMitarbeiter grpLeiter = new Gruppenleiter();
            IMitarbeiter teamleiter = new Teamleiter();
            IMitarbeiter teamleiter2 = new Teamleiter2();
            IMitarbeiter chef = new Chef();
 
            List<imitarbeiter> objMitarbeiter = new List<imitarbeiter>();
 
 
            objMitarbeiter.Add(grpMitarbeiter);
            objMitarbeiter.Add(grpLeiter);
            objMitarbeiter.Add(teamleiter2);
            objMitarbeiter.Add(teamleiter);
            objMitarbeiter.Add(chef);
 
 
            IColor txtWeiss = new Weiss();
            txtWeiss.Draw();
             
            foreach (IMitarbeiter obj in objMitarbeiter)
            {
                //obj.Bezeichnung();
                Console.WriteLine(obj.GetType() + "\n> " + obj.Bezeichnung());
            }
 
            Console.ReadLine();
        }
    }
}
 
</imitarbeiter></imitarbeiter>

Und so sieht es aus: