- Details
- Geschrieben von: Gerrit
- Kategorie: Design Patterns
- Zugriffe: 3553
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:
- Details
- Geschrieben von: Gerrit
- Kategorie: Design Patterns
- Zugriffe: 4187
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:
- Details
- Geschrieben von: Gerrit
- Kategorie: Design Patterns
- Zugriffe: 7997
Ein Beispiel für den Aufbau einer abstrakten Klasse in C#
Im Beispiel werden zur Demonstration nicht abstrakte Klassen implementiert (Addition und PI) sowie die Abstrakte für Subtraktion, Division und Multiplikation
using System;
using System.Globalization;
namespace AbstractClass
{
abstract class Calculator
{
public double Addition(double num1, double num2) //non abstract method
{
return (num1 + num2);
}
public abstract double Multiplikation(double num1, double num2); //abstract method
public abstract double Division(double num1, double num2); //abstract method
public abstract double Subtraktion(double num1, double num2); //abstract method
}
class Program : Calculator
{
public override double Multiplikation(double n1, double n2)
{
return (n1 * n2);
}
public override double Division(double n1, double n2)
{
return (n1 / n2);
}
public override double Subtraktion(double n1, double n2)
{
return (n1 - n2);
}
static void Main(string[] args)
{
Program obj = new Program();
const string fehlermeldung = "Bitte eine gültige Zahl - Format: #.#";
// Abfrage der Werte
Console.WriteLine("PI");
double pi = GetUserInput("Ein Wert:", fehlermeldung);
Console.WriteLine("Addition | Multiplikation | Subtraktion");
double a = GetUserInput("1. Wert:", fehlermeldung);
double b = GetUserInput("2. Wert:", fehlermeldung);
Console.WriteLine("Division | Eingabe von 0 nicht erlaubt");
double aZero = GetUserInput("1. Wert:", fehlermeldung, false);
double bZero = GetUserInput("2. Wert:", fehlermeldung, false);
// Berechnungen durchführen
double resultPi = pi*Math.PI;
double resultAddition = obj.Addition(a, b);
double resultSubtraktion = obj.Subtraktion(a, b);
double resultMultiplikation = obj.Multiplikation(a, b);
double resultDivision = obj.Division(aZero, bZero);
// Ausgabe an Benutzer
Console.WriteLine("\nErgebnisse:");
Console.WriteLine("PI\t\t:{0}*{1}={2}", pi, Math.PI.ToString(CultureInfo.InvariantCulture), resultPi);
Console.WriteLine("Addition\t:{0}+{1}={2}", a, b, resultAddition);
Console.WriteLine("Subtraktion\t:{0}-{1}={2}", a, b, resultSubtraktion);
Console.WriteLine("Multiplikation\t:{0}*{1}={2}",a,b, resultMultiplikation);
Console.WriteLine("Division\t:{0}+{1}={2}",aZero, bZero, resultDivision);
Console.ReadLine();
}
static double GetUserInput(string question, string errorMessage, Boolean allowZero = true)
{
double a;
Console.Write(question);
if (double.TryParse(Console.ReadLine(), out a) )
{
if (!allowZero && (int)a == 0)
{
Console.WriteLine("0 nicht erlaubt.");
a = GetUserInput(question, errorMessage);
}
}
else{
Console.WriteLine(errorMessage );
a = GetUserInput(question, errorMessage);
}
return a;
}
}
}