diff --git a/README.md b/README.md index 9f1cb9d..a4d367e 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,9 @@ * Nikolai - [State](state.md) * Marcel - [Iterator](iterator.md) * Tim - [Decorator](decorator.md) + +## Markdown helper + +* [Markdown Cheat Sheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) +* [GitHub flavored markdown](https://guides.github.com/features/mastering-markdown/) +* [Markdown Linter](https://dlaa.me/markdownlint/) diff --git a/decorator.md b/decorator.md new file mode 100644 index 0000000..0feb69c --- /dev/null +++ b/decorator.md @@ -0,0 +1,83 @@ +# Decorator Pattern + +## Beschreibung + +Beim Decorator Pattern kann beliebige Funktionalität zu Objekten hinzugefügt +werden. Es gibt Basisklassen (Components/Komponenten). Diese werden mit +Decorators/Dekorierer erweitert. Decorator und Component sind vom gleichen Typ +(abstrakte Basisklasse oder Interface). Dekorator ruft immer die unterliegende +Implementierung einer Methode auf, und davor oder danach seine eigene. +Dekorators können beliebig verschachtelt werden. + +## Vorteile + +* Manipulation von Klassen kann zur Laufzeit und während dem Kompilieren +erfolgen +* Beliebige (Mehrfach)Kombination von Decorators ist möglich +* Das Interfaces, welches Clients nutzen, bleibt unverändert +* Klassen sind sehr kurz und übersichtlich, Sie implementieren nur das nötigste + +## Nachteile + +* Ggf sehr viele Klassen, dies kann unübersichtlich werden + +## Beispiel + +```csharp + public abstract class Component + { + public abstract void operate(); + } + + public class ConcreteComponent1 : Component + { + override public void operate() + { + Console.WriteLine("this is a concrete component"); + } + } + + public class ConcreteComponent2 : Component + { + public override void operate() + { + Console.WriteLine("This is another concrete component"); + } + } + + public class ConcreteDecorator1 : Decorator + { + public ConcreteDecorator1(Component component) : base(component) + { + + } + override public void operate() + { + component.operate(); + Console.WriteLine("This is a concrete decorator number one"); + } + } + + + public abstract class Decorator : Component + { + protected Component component; + + public Decorator(Component component) + { + this.component = component; + } + } + + class Program + { + static void Main(string[] args) + { + Component CompA = new ConcreteComponent1(); + CompA.operate(); + CompA = new ConcreteDecorator1(CompA); + CompA.operate(); + Console.ReadLine(); + } + } +``` diff --git a/iterator.md b/iterator.md new file mode 100644 index 0000000..ed90b5c --- /dev/null +++ b/iterator.md @@ -0,0 +1,189 @@ +# Iterator-Pattern + +## Definition + +Das Iterator-Pattern wird verwendet, um über eine Liste zu traversieren ohne hier entsprechend die Struktur oder das Muster zu +veröffentlichen. Heißt, eine Liste nach und nach Abzugehen. Der Iterator ist in diesem Fall der `Cursor`, welche durch die Kollektion +durchgeht. + +## UML + +![alt text](iterator_uml.png) + +## Anwendung + +Um einen Iterator Anwenden zu können, muss zuvor ein Iterator Interface angelegt werden, wo die entsprechenden Methoden (next, +first,isDone und CurrentItem) erzeugt werden. Anschließend wird ein ConcreteIterator als Klasse definiert, damit der Iterator weiß, an +welcher Stelle dieser sich gerade befindet. + +Beispielcode für die Erstellung und Erzeugung eines Iterator-Pattern: + +### Erzeugen des Iterator Interfaces + +```csharp +interface IIterator +{ + string FirstItem { get;} + string NextItem{ get;} + string CurrentItem{ get;} + bool IsDone { get;} +} +``` + +### Erzeugen des Interfaces für die Aggregator Kollektion + +```csharp +interface IAggregate +{ + IIterator GetIterator(); + string this[int itemIndex]{set;get;} + int Count{get;} +} +``` + +#### Erzeugen der Konkreten Klasse für die Aggreator Kollektion + +```csharp +class MyAggregate : IAggregate +{ + List values = null; + + public MyAggregate() + { + values = new List(); + } + + #region IAggregate Members + + public IIterator GetIterator() + { + return new MyIterator(this); + } + + #endregion + + public string this[int itemIndex] + { + get + { + if (itemIndex < values_.Count) + { + return values[itemIndex]; + } + else + { + return string.Empty; + } + } + set + { + values.Add(value); + } + } + + public int Count + { + get + { + return values.Count; + } + } +} +``` + +#### Implementieren des Konrekten Interator + +```csharp +class MyIterator : IIterator +{ + IAggregate aggregate = null; + int currentIndex = 0; + + public MyIterator(IAggregate aggregate) + { + aggregate = aggregate; + } + + #region IIterator Members + + public string FirstItem + { + get + { + currentIndex = 0; + return aggregate[currentIndex]; + } + } + + public string NextItem + { + get + { + currentIndex += 1; + + if (IsDone == false) + { + return aggregate[currentIndex]; + } + else + { + return string.Empty; + } + } + } + + public string CurrentItem + { + get + { + return aggregate[currentIndex]; + } + } + + public bool IsDone + { + get + { + if (currentIndex < aggregate.Count) + { + return false; + } + return true; + } + } + + #endregion +} +``` + +#### Einfügen in das eigentliche Programm + +```csharp +class Program +{ + static void Main(string[] args) + { + MyAggregate aggr = new MyAggregate(); + + aggr[0] = "1"; + aggr[1] = "2"; + aggr[2] = "3"; + aggr[3] = "4"; + aggr[4] = "5"; + aggr[5] = "6"; + aggr[6] = "7"; + aggr[7] = "8"; + aggr[8] = "9"; + aggr[9] = "10"; + + IIterator iter = aggr.GetIterator(); + + for (string s = iter.FirstItem; iter.IsDone == false; s = iter.NextItem ) + { + Console.WriteLine(s); + } + } +} +``` + +Quelle: [Codeproject](https://www.codeproject.com/Articles/362986/Understanding-and-Implementing-the-Iterator-Patter) diff --git a/iterator_uml.png b/iterator_uml.png new file mode 100644 index 0000000..be03eab Binary files /dev/null and b/iterator_uml.png differ diff --git a/observer.md b/observer.md new file mode 100644 index 0000000..2c948b9 --- /dev/null +++ b/observer.md @@ -0,0 +1,103 @@ +## Observer-Pattern + +Das Observer Pattern ermöglicht, dass sich Objekte (Observer, beobachtendes Objekt) +bei einem anderen Objekt (Subjekt, beobachtetes Objekt) registrieren und fortan vom +diesem informiert werden, sobald es sich ändert. + +Die Idee hinter dem Pattern liegt darin, das sich Teile von einem Programm (meist grafische Elemente), +die identische Quellen benutzen, benachrichtigt werden, wenn sich etwas ändert. + +Es werden dafür mindestens 3 Klassen benötigt. +Zu einem das Subjekt, bei dem sich der Konkrete Observer anmelden, abmelden, und benachrichtig wird. +Das Observer Interface stellt den Observern die "Update" Methode zur verfügung die von jedem Observer implementiert werden muss. +Und die Konkreten Observer können bei einer Benachrichtigung dann mit der Daten des Subjektes arbeiten. + +### Beispielcode + +#### Subjekt-Klasse + +```csharp +public abstract class Subject +{ + // Eine Liste zum verwalten von den angemeldeten Observern + private List observerList = new List(); + + // Observer wird in die Observerliste hinzugefügt + public void attach(Observer newObserver) + { + observerList.add(newObserver); + } + + // Observer wird aus der Liste entfernt + public void detach(Observer newObserver) + { + observerList.remove(newObserver); + } + + // Allen observer in der Liste wird der neue Werd übergeben bzw. deren Update Methode wird aufgerufen. + protected void notifyObservers(int state) + { + for (Observer observer : observerList) + { + observer.update(state); + } + } +} +``` + + +#### Konkretes-Objekt + +```csharp + +public class ConcretSubjekt : Subject +{ + private int state; + + public Setstate(int value) + { + state = value; + } + + public int Getstate() + { + return state; + } +} +``` + +#### Observer-Klasse + +```csharp +public Interface Observer +{ + public void Update(int state) +} + +public class ConcretObserver : Observer +{ + void Update(int state) + { + Console.Writeline("Mein status ist : " + state); + } +} +``` + +#### Beispielclient + +```csharp + +public class client +{ + public void test() + { + ConcretSubjekt SubjectA = new ConcretSubjekt(); + ConcretSubjekt.attach = new ConcretObserver(); + + ConcretSubjekt.Setstate(2); + // Ausgabe in der Console: "Mein Status ist : 2" + ConcretSubjekt.Setstate(5); + // Ausgabe in der Console: "Mein Status ist : 5" + } +} +``` diff --git a/singleton.md b/singleton.md new file mode 100644 index 0000000..df2be11 --- /dev/null +++ b/singleton.md @@ -0,0 +1,24 @@ +## Singleton-Pattern + +### Das Singleton als Erzeugungsmuster gewährleistet, dass ein Objekt nur einmal im Speicher vorhanden ist + +#### +Der Zugriffsmodifikator "private" für den Standard-Konstruktor verhindert die Erzeugung von Objekte durch diesen. +Statt dessen erfolgt die Instanzierung durch eine Klassenmethode, welche das Objekt in einer statischen Klassenvariablen speichert. +Dies geschieht beim erstmaligen Aufruf der Methode. Bei weiteren Aufrufen wird lediglich das Objekt als Variable zurückgegeben. + +```csharp + + public class TSingleton + { + private TSingleton() { } + + private TSingleton instance; + + public TSingleton Get_Instance() + { + if (instance == null) { instance = new TSingleton(); } + return instance; + } + } +``` diff --git a/state.md b/state.md new file mode 100644 index 0000000..8fafd5f --- /dev/null +++ b/state.md @@ -0,0 +1,77 @@ + +# State Pattern + +## Definition +Erlaubt einem Objekt, sein Verhalten selbständig zu ändern, wenn sich sein interner Zustand ändern soll. + +## Aufbau +Zunächst wird ein Objekt benötigt, welches verschiedene Status besitzt. +In diesem Beispiel ist es eine Ampel, welche den Status Rot und Grün besitzen kann. +Desweiteren benötigt das Objekt Funktionen zum Verändern des Zustandes, in diesem Fall das **Schalten**. +Dieses Objekt, bzw. die Funktionen können dann beliebig erweitert werden. +Ein Konto hat z.B. ein Besitzer der sich ändern kann und einen Geldbetrag. + +## Code + +### Status Klassen + +#### Vorgabe der Status Funktionen durch abstract +```csharp +abstract class Licht +{ + public abstract void Handle(Ampel aktuelleAmpel); +} +``` + +#### Definition Status und Aktion die durchgeführt werden soll +```csharp +class Rot : Licht +{ + public override void Handle(Ampel aktuelleAmpel) { + aktuelleAmpel.StatusLicht = new Gruen(); + } +} + +class Gruen : Licht +{ + public override void Handle(Ampel aktuelleAmpel) { + aktuelleAmpel.StatusLicht = new Rot(); + } +} +``` + +### Objekt mit verschiedenen Status +```csharp +class Ampel +{ + //Aktueller Status + private Licht _statusLicht; + + //Initialisierung + public Ampel (Licht DefaultLicht) { + this._statusLicht = DefaultLicht; + } + + // Get / Set aktueller Status + Ausgabe von neuen Wert + public Licht StatusLicht { + get { return _statusLicht; } + set { + this._statusLicht = value; + Console.WriteLine("Ampel Farbe: " + _statusLicht.GetType().Name); + } + } + + public void Schalte() + { + this._statusLicht.Handle(this); + } +} +``` + +### Beispiel Main Aufruf +```csharp +Ampel Fussgaenger = new Ampel(new Rot()); + +Fussgaenger.Schalte(); +Fussgaenger.Schalte(); +``` diff --git a/strategy.md b/strategy.md new file mode 100644 index 0000000..f3705b3 --- /dev/null +++ b/strategy.md @@ -0,0 +1,79 @@ +# Strategy Pattern + +## Definition + +Das Strategypattern ermöglicht es, den Algorithmus unabhängig von ihn nutzenden Klienten zu variieren. + +## Aufbau + +Das Verhalten eines Objekts wird in eine Klasse (Strategieklasse) ausgelagert. Für jedes Verhalten existiert eine Klasse. +Jede Klasse die das Verhalten nutzen soll kann eine Instanz der Strategieklasse nutzen. +Es wird nicht mit der konkreten Implementierung des Verhaltens, sondern mit einem Interface gearbeitet. + +## Code + +### Strategy-Interface + Konkrete Strategy + +```csharp +interface Strategy() +{ + public void Algorithm(); +} + +class ConcreteStrategy1() : Strategy +{ + public void Algorithm() + { + //Code + } +} + +class ConcreteStrategy2() : Strategy +{ + public void Algorithm() + { + //Code + } +} + +class ConcreteStrategy3() : Strategy +{ + public void Algorithm() + { + //Code + } +} +``` + +### Kontext + +```csharp +abstract class Context +{ + //Instanzvariable. Standartverhalten. + Strategy strategy = new ConcreteStrategy1(); + + public void setStrategy (Strategy strategy) + { + this.strategy = strategy; + } + + public void Behavior() + { + //Zuweisung des Verhaltens an Verhaltensobjekt + strategy.Behavior(); + } +} +``` + +### Klient + +```csharp +public class Client +{ + Context context = new Context(); + context.Behavior(); //Standartverhalten + context.setStrategy(new ConcreteStrategy2); + context.Behavior(); //ConcreteStrategy2 Verhalten +} +```