| Design Pattern: Strategy |
|
| Development |
| Tuesday, 04 April 2006 16:06 |
|
Heute denken wir uns einmal eine Strategie aus, wie wir Problemstellungen in unseren Anwendungen schneller, flexibler und einfacher lösen können. Dieser Artikel beschreibt die exemplarische Implementierung des Entwurfsmuster Strategie (Strategy) in Visual FoxPro. Schauen wir uns zunächst einmal wieder die Definition aus der Wikipedia an: Strategie-Objekte werden ähnlich wie Klassenbibliotheken verwendet. Im Gegensatz dazu handelt es sich jedoch nicht um externe Programmteile, die als ein Toolkit genutzt werden können, sondern um integrale Bestandteile des eigentlichen Programms, die deshalb als eigene Objekte definiert wurden, damit sie durch andere Algorithmen ausgetauscht werden können. Meistens wird eine Strategie durch Klassen umgesetzt, die eine bestimmte Schnittstelle implementieren. In Sprachen wie Smalltalk, in denen auch der Programmcode selbst in Objekten abgelegt werden kann, kann eine Strategie aber auch durch solche Code-Objekte realisiert werden. Die Verwendung von Strategien bieten sich an, wenn Hat jemand was verstanden? Ich hab's auf den ersten Blick ehrlich gesagt nicht kapiert und mir daher mal verschiedene Gedanken über den obigen Inhalt gemacht. Dabei bin ich von der Situation viele verwandte Klassen sich nur in ihrem Verhalten unterscheiden aus gestartet. Okay, also viele verwandte Klassen bedeutet zunächst, dass eine abstrakte Klasse und zig Ableitungen davon gibt, die alle über die gleiche Schnittstelle verfügen. Soweit ja noch klar. Damit können wir sicherstellen, dass die einzelnen Klassen austauschbar werden und wir erhalten Flexibilität und Wiederverwendbarkeit. Jetzt brauchen wir noch irgendetwas, welches wir als Ansprechpartner innerhalb unserer Anwendung nutzen können. Diese Komponente trägt dann auch dafür Sorge, dass die jeweilige Instanz des gewünschten Verhaltens verwendet wird. Wir müssen uns also nicht mehr drum kümmern, sondern unterhalten uns nur mit dieser Komponente. Somit kapseln wir die einzelnen Strategien vom Klienten. Gut, damit ergeben sich für uns folgende Erkenntnisse: Unsere Anforderung Abstrakte Strategie *//- Abtrakte Basisklasse für alle Exporttypen (abstrakte Strategie) Define Class AbstraktExport As Custom && Abstract Strategy cDateierweiterung = "" cVerzeichnis = "" cDatei = "" cBeschriftung = "" Function Schreiben() As Boolean EndFunc EndDefine Ganz einfach gehalten. Es gibt ein Informationen zur Ausgabedatei und die eigentliche Methode zum Erzeugen der Ausgabe. Konkrete Strategie(n) *--- Export als kommaseparierte Liste (CSV) Define Class ExportCsv As AbstraktExport && (konkrete Strategie) cDateierweiterung = ".txt" cBeschriftung = "Export als kommaseparierte Liste" Function Schreiben() As Boolean Local llOk, lcAlias llOk = .T. lcAlias = Alias() Select(m.lcAlias) Try Copy To (This.cDatei + This.cDateierweiterung) Type Csv Catch llOk = .F. EndTry Return m.llOk EndFunc EndDefine *--- Export nach XML *--- Export nach Excel (einfach) Insgesamt gewohnter Anblick und vertraute VFP-Befehle. Dennoch sehen wir, dass der Export nach Excel und CSV über Copy To erfolgt, während die Ausgabe nach XML über CursorToXML() realisiert wird. Und hier zeichen sich bereits die ersten Vorteile unserer Strategie ab. Egal, welches Ausgabeformat wir haben wollen, würden wir aktuell immer nur die Methode Schreiben() ausführen. Die Kapselung (oder der Kontext) *--- Verwaltungsklasse unserer Ausgabeformate Define Class ExportHandler As Custom && (Kontext) Protected oExportTyp oExportTyp = .Null. Function Init() As Boolean *--- Initialen Exporttyp laden (Default) This.oExportTyp = CreateObject("ExportXml") EndFunc Function Destroy() As Boolean Function SetzeExportTyp(tcExportTyp As String) As Boolean Function GebeExportTyp() AS String Function Schreiben(tcDateiname As String) As Boolean Return This.oExportTyp.Schreiben() Function ToXml(tcDateiname As String) As Boolean Ich habe hier zwei Ansätze in der Klasse implementiert: - Allgemeiner Ansatz, wir haben die Kontrolle über das gewünschte Ausgabeformat - Vereinfachte Methoden (ToCvs, ToXml, etc.) Und so langsam dürfte erkennbar sein, warum das Entwurfsmuster Strategie sehr nützlich ist. Wir müssen nun in unserer Anwendung nur noch den Kontext instanziieren und alles weitere geht dann automatisch. oExport = CreateObject("ExportHandler")
oExport.SetzeExportTyp("Excel") ? oExport.Schreiben("C:TempMeinExportExcel") ? oExport.ToXml("C:TempMeinExportXML") Ausbaustufen Die Methode im Kontext zum Einstellen des gewünschten Exporttyps kann man übrigens noch problemlos aufbohren. Wir haben in unseren Anwendungen eine Verwaltungstabelle für verschiedene Import- und Exportformate. Dabei nutzen wir innerhalb der Anwendung, so wie hier im Code Tokens und setzen eine Abfrage auf die Tabelle ab, um die Informationen zu Klassenname, Klassenbibliothek, Beschriftung, Dateierweiterung, etc. in Erfahrung zu bringen. Das gezeigte Beispiel behandelt den Export von Informationen. Natürlich lässt sich das Konzept auch auf andere Szenarien anwenden, hier mal ein paar Möglichkeiten: Import *g*, Verschlüsselung, Konvertierung, und so weiter... Übrigens, wenn man den Druck ebenfalls als Datenexport betrachtet, braucht man lediglich eine neue Klasse zu schreiben und anzubinden. Was potentiell für einfache Reports sehr praktisch sein kann. *--- Export als Druckdokument
Define Class ExportReport As AbstraktExport Protected cReportDatei cReportDatei = "Schnellausgabe.frx" Function Schreiben() As Boolean Local llOk, lcAlias llOk = .T. lcAlias = Alias() Select(m.lcAlias) Try Report Form (This.cReportDatei) To Printer Prompt Catch llOk = .F. EndTry Return m.llOk EndFunc EndDefine Okay, jetzt aber genug... Ich hoffe, dass dieser Artikel das grundsätzliche Konzept des Strategie-Muster ausreichend erklärt, und dass der gezeigte Quellcode leicht verständlich sowie nachvollziehbar ist.
|





