Was bleibt gleich? Was ändert sich?
Die Muster sind die gleichen. Die Sprachtechniken ändern sich.
Gibt es Leitprinzipien wie SOLID,
Ja. In der Tat bleiben sie die Leitprinzipien. Nichts verändert sich.
oder kanonische Muster (vielleicht völlig neue), die ein Neuling in einer dynamischen Sprache kennen sollte?
Einige Dinge sind einzigartig. Die Auswirkung besteht hauptsächlich darin, dass sich die Implementierungstechniken ändern.
Ein Muster ist - na ja - ein Muster . Kein Gesetz. Kein Unterprogramm. Kein Makro. Es ist nur eine gute Idee, die wiederholt wird, weil es eine gute Idee ist.
Gute Ideen kommen nicht aus der Mode oder ändern sich dramatisch.
Weitere Hinweise. Python ist nicht "schwach typisiert". Es ist stärker typisiert als Java oder C ++, da es keine Cast-Operation gibt. [Ja, es gibt eine Möglichkeit, die mit einem Objekt verknüpfte Klasse zu verfälschen, aber es ist nichts, was getan wird, außer um einen pingeligen, legalistischen Punkt zu beweisen.]
Ebenfalls. Die meisten Entwurfsmuster basieren auf verschiedenen Möglichkeiten, den Polymorphismus auszunutzen.
Schauen Sie sich als Beispiele State oder Command oder Memento an. Sie haben Klassenhierarchien, um polymorphe Zustände, Befehle oder Andenken an Zustandsänderungen zu erstellen. Wenn Sie dies in Python tun, ändert sich nichts wesentlich. Zu den geringfügigen Änderungen gehört die Lockerung der genauen Klassenhierarchie, da der Polymorphismus in Python von gängigen Methoden abhängt, nicht von gemeinsamen Vorfahren.
Einige Muster sind auch nur ein Versuch, eine späte Bindung zu erreichen. Die meisten Factory- bezogenen Muster sind ein Versuch, eine einfache Änderung einer Klassenhierarchie zu ermöglichen, ohne jedes C ++ - Modul in der Anwendung neu zu kompilieren. Dies ist keine so interessante Optimierung in einer dynamischen Sprache. Eine Factory als Möglichkeit, Implementierungsdetails zu verbergen, hat jedoch immer noch einen enormen Wert.
Einige Muster sind ein Versuch, den Compiler und den Linker anzutreiben. Singleton existiert zum Beispiel, um verwirrende Globals zu erstellen, diese aber zumindest zu kapseln. Python-Singleton-Klassen sind keine angenehme Aussicht. Aber Python-Module sind bereits Singletons, daher verwenden viele von uns nur ein Modul und vermeiden es, sich mit einer Singleton- Klasse herumzuschlagen .
Peter Norvig hat sich 1998 genau dieser Frage gestellt. Lesen Sie http://norvig.com/design-patterns/ppframe.htm, um eine Reihe detaillierter Informationen zu erhalten, und http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures for weitere Diskussion um den Punkt.
Die kurze Version besagt, dass sich wiederholende Entwurfsmuster einfacher werden, wenn Ihre Sprache mehr Funktionen enthält - oft bis sie unsichtbar sind. Er stellte fest, dass dies für die meisten von der GoF identifizierten Entwurfsmuster zutraf.
quelle
Das Programmieren in einer dynamischen objektorientierten Sprache verwendet viele der gleichen Muster und Prinzipien, aber es gibt bestimmte Verbesserungen und Unterschiede aufgrund der Umgebung:
Ersetzen Sie Schnittstellen durch Ententypisierung - Wenn die Viererbande Sie auffordert, eine abstrakte Basisklasse mit rein virtuellen Funktionen zu verwenden, und Sie eine Schnittstelle in Java in einer dynamischen Sprache verwenden, benötigen Sie nur ein Verständnis. Da Sie jedes Objekt überall verwenden können und es einwandfrei funktioniert, wenn es die tatsächlich aufgerufenen Methoden implementiert, müssen Sie keine formale Schnittstelle definieren. Es kann sich lohnen , eine zu dokumentieren , damit klar ist, was tatsächlich erforderlich ist.
Funktionen sind auch Objekte - Es gibt viele Muster, bei denen es darum geht, Entscheidung von Aktion zu trennen. Befehl, Strategie, Verantwortungskette usw. In einer Sprache mit erstklassigen Funktionen ist es oft sinnvoll, eine Funktion einfach weiterzugeben, anstatt Objekte mit
.doIt()
Methoden zu erstellen. Diese Muster wandeln sich in "eine Funktion höherer Ordnung verwenden" um.VERKAUFT - Das Prinzip der Schnittstellentrennung ist hier am stärksten betroffen, da keine Schnittstellen vorhanden sind. Sie sollten das Prinzip weiterhin berücksichtigen, es jedoch nicht in Ihren Code umwandeln. Nur persönliche Wachsamkeit schützt Sie hier. Auf der anderen Seite ist der Schmerz, der durch die Verletzung dieses Prinzips verursacht wird, in üblichen dynamischen Umgebungen stark reduziert.
"... in meiner eigenen besonderen ... Redewendung!" - Jede Sprache hat gute und schlechte Praktiken, und Sie müssen sie lernen und befolgen, wenn Sie den besten Code in diesen Sprachen wünschen. Ein perfekt geschriebenes Iteratormuster kann beispielsweise in einer Sprache mit integriertem Listenverständnis ausgelacht werden.
quelle
Nach meiner Erfahrung sind einige Muster in Python immer noch nützlich und noch einfacher einzurichten als in statischeren Sprachen. Einige Patterns OTOH werden einfach nicht benötigt oder sind sogar verpönt, wie das Singleton-Pattern. Verwenden Sie stattdessen eine Variable oder Funktion auf Modulebene. Oder verwenden Sie das Borg-Muster.
Anstatt ein Erstellungsmuster einzurichten, reicht es oft aus, ein aufrufbares Muster zu übergeben, das Objekte erstellt. Das kann eine Funktion, ein Objekt mit einer
__call__
Methode oder sogar eine Klasse sein, da esnew()
in Python keine gibt , nur einen Aufruf der Klasse selbst:Status- und Strategiemuster haben in Sprachen wie C ++ und Java eine sehr ähnliche Struktur. Weniger in Python. Das Strategiemuster bleibt mehr oder weniger gleich, aber das Zustandsmuster wird größtenteils unnötig. Das Zustandsmuster in statischen Sprachen simuliert den Klassenwechsel zur Laufzeit. In Python können Sie genau das tun: Ändern Sie die Klasse eines Objekts zur Laufzeit. Solange Sie dies kontrolliert und gekapselt tun, sollte es Ihnen gut gehen:
Muster, die auf statischem Typversand basieren, funktionieren nicht oder ganz anders. Sie müssen nicht so viel Code für die Kesselplatte schreiben, z. B. Besuchermuster: In Java und C ++ müssen Sie in jeder besuchbaren Klasse eine Akzeptanzmethode schreiben, während Sie in Python diese Funktionalität über eine Mixin-Klasse wie Visitable erben können:
Viele Situationen, in denen ein Muster in einer statischen Sprache angewendet werden muss, tun dies in Python weniger. Viele Dinge können mit anderen Techniken gelöst werden, wie Funktionen höherer Ordnung (Dekoratoren, Funktionsfabriken) oder Metaklassen.
quelle
__class__
zur Implementierung einer Factory in Python eine gute Idee?