© saicle/Shutterstock.com
Design Patterns sind mehr als OOP-Emulation

Advanced JavaScript Trickery


Wer über Design Patterns für JavaScript schreibt, beginnt normalerweise mit einem Elaborat über die Besonderheiten von prototyporientierten Sprachen. Dies ist mit Sicherheit nicht unrichtig – wer von .NET in Richtung JavaScript übersiedelt, hat mit dem System seine Schwierigkeiten.

Zur Umgehung dieses Problems hat sich im Laufe der Jahre eine Gruppe von Patterns herauskristallisiert, die die Emulation von Objekten in JavaScript erlauben. Aufgrund ihrer enormen Wichtigkeit werden sie immer wieder in Fachmagazinen behandelt. Im folgenden Artikel setzen wir dieses Wissen als gegeben voraus, und wenden uns stattdessen einer Gruppe von anderen, nicht weniger interessanten Themen zu.

Zustandsautomaten

Wer einmal mit PhoneGap gearbeitet hat, kennt die Problematik der asynchronen Programmierung mit Sicherheit. Beim Abarbeiten von einer Gruppe von asynchronen Aufrufen ist für jede Stufe der Verarbeitung eine eigene Erfolgsmethode notwendig, die den nächsten Schritt einleitet.

In meinem Lehrbuch zum Thema PhoneGap findet sich das folgende Beispiel. Seine genaue Funktion ist an dieser Stelle nicht relevant – wichtig ist nur, dass das erfolgreiche Abarbeiten von getFile zu einem Aufruf von SuccessSv1 führt. Danach wird createWriter aufgerufen, ein Erfolg an dieser Stelle wird in successSv2 angezeigt (Listing 1).

Listing 1

function processStore() { myFileSystem.root.getFile("newFile.txt", {create: true, exclusive: false}, successSv1, fail); } function successSv1(_newFileEntry) { _newFileEntry.createWriter(successSv2, fail); } function successSv2(_writer) { _writer.onwrite=function(_evt) { document.getElementById('TxtStatus').value="Write Success"; } . . . _writer.write(document.getElementById('TxtResultA').value); }

Dieses Problem lässt sich durch die Verwendung eines Zustandsautomaten umgehen. Die ausführliche Behandlung dieses (faszinierenden) Themas würde das ganze Heft füllen; wir begnügen uns an dieser Stelle deshalb mit einer Kurzfassung.

Ein Zustandsautomat ist ein Programm, dessen Reaktion auf ein eingehendes Ereignis nur (oder primär) vom im System gespeicherten Zustand abhängt. Eingehende Ereignisse führen unter Umständen zu Zustandsänderungen. In unserem Fall wäre der Erfolgs-Callback ein dankbarer Kandidat für die Realisierung per Zustandsautomat. Je nach Wert der Zustandsvariable folgt auf den eingehenden Erfolgsimpuls ein anderes Ereignis.

PhoneGap-erfahrene Entwickler schreien an dieser Stelle auf, da die zurückgegebenen Datentypen je nach Art des Erfolgsereignisses anders aussehen. Das ist völlig unnötig – der prototypbasierte Aufbau der Sprache wirkt sich hier zu ihren Gunsten aus.

Grob vereinfacht erfolgt die Prüfung auf Plausibilität eines Aufrufs erst dann, wenn die Runtime den Code abarbeitet. Das bedeutet, dass eine Struktur nach dem Schema in Listing 2 völlig legitim wäre.

Listing 2

var myStates; function doSomething(_e) { if(myStates=="bisnovat") { var rakete=_e; rakete.hitEnemyAircraft(); } else if(myStates=="assistentin") { var sektVernichter=_e; sektVernichter.seiFroehlich(sektVernichter .myGrund); } }

Die Assistentin und der Torpedo reagieren auf ein eingehendes Ereignis mit komplett verschiedenen Methoden, die zudem verschiedene Signaturen haben. Trotzdem funktioniert alles ohne Probleme – zumindest solange, wie die doSomething-Methode immer nur mit den richtigen Parametern und im richtigen Zustand aufgerufen wird.

Wenn Sie die Robustheit ihres Programms erhöhen möchten, so können Sie das Objekt vorher analysieren. Ist die Methode hitEnemyAircraft null, so haben Sie es mit einer Assistentin zu tun. Wenn der Zustandsautomat trotzdem auf bisnovat steht, so gibt es einen Fehler in der Aufruflogik.

Typen und Enten

Im englischsprachigen Raum hat sich für diese Vorgehensweise die Bezeichnung Duck Typing eingebürgert. Sie geht auf James Whitcomb Riley zurück, dessen „Duck Test“ nach folgendem Schema erfolgt: „Wenn ich einen wie eine Ente quakenden, gehenden und schwimmenden Vogel sehe, so bezeichne ich ihn als Ente.“ Das bedeutet für Sie als Entwickler, dass jedes Objekt als „Instanz einer Klasse“ gilt, solange es die zu diesem Zeitpunkt erforderlichen Methoden implementiert.

Vererbung für Dummys

Die soeben besprochenen Eigenheiten der Sprache erleichtern das Implementieren von einer an Vererbung erinnernden Art der „objektorientierten“ Programmierung. Der Zustandsautomat würde jedes beliebige Objekt als Assistentin erkennen, das eine seiFroehlich-Methode und ein myGrund-Element enthält – wenn diese Funktionen im Torpedo enthalten wären, so wäre die Bisnovat aus JavaScript-Sicht eine legitime Assistentin.

OOP-Experten sind mit dieser simplifizierten Darstellung mit Sicherheit unzufrieden. Trotzdem lässt sich die „Essenz“ von Vererbung nachbilden, indem man die Klasseninstanzen um die fehlenden Attribute erweitert.

Im Laufe der Jahre haben sich zwei verschiedene Methoden zur Realisierung von Vererbung herauskristallisiert. Die weiter verbreitete Vorgehensweise basiert auf der Idee, dass ein Objekt aus einer Basis und einer Gruppe von Erweiterungen besteht.

Sie ist im folgenden Snippet illustriert – falls ihr Browser die Funktion Object.create() nicht implementiert, so mü...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang