Ein Pattern (Muster) ist eine Art Schablone zur Lösung eines bestimmten Softwareproblems. In der Softwareentwicklung nennt man es dann Design Pattern (Entwurfsmuster). Ein Pattern ist sprachenunabhängig und dient zur Lösung immer wiederkehrender Probleme, wobei jedes Pattern genau ein Problem löst. In welcher Sprache das Pattern später implementiert wird, ist erst einmal egal. Als Beispiel seien das Singleton Pattern, das dafür sorgt, dass es von einer bestimmten Klasse immer nur genau eine Instanz gibt und das Observer Pattern genannt, das die Eventverwaltung in .NET löst. Ein etwas unbekannteres Pattern ist sicherlich das Nullobjekt Pattern. Es besagt, dass jede Referenz auf Variablen bzw. andere Objekte nie null gesetzt werden, wenn man sie nicht mehr braucht. Stattdessen wird ein leeres Objekt zugewiesen. So versucht man zu vermeiden, dass NullReferenceExceptions entstehen. Aber jede Medaille hat zwei Seiten und so haben alle Patterns auch ihre Nachteile, wobei die Vorteile allerdings überwiegen. Aktuell ist es modern, das gute alte switch Statement durch ein Strategy Pattern zu ersetzen, was ich als sehr angenehm empfinde. Wenn ein neuer switch-Zweig hinzukommt, braucht man den Code dort wo das switch stehen würde, gar nicht mehr anfassen. Das verringert die Fehleranfälligkeit und bringt mehr Struktur in den Code, sofern man sich auf solche Pattern einlässt. Es gibt auch Anti-Patterns, also Muster die zeigen, wie man etwas nicht machen sollte. Aufgrund von Erfahrungen in der Softwareentwicklung entpuppten sich einige Ideen im Laufe der Zeit bzw. mit der Weiterentwicklung von Tools, Entwicklungs- bzw. Laufzeitumgebungen als ungeeignet, weil bestimmte Gegebenheiten vorher nicht berücksichtigt werden konnten. Patterns an sich sind eine tolle und gute Sache. Sie helfen etwas Struktur in den Quellcode zu bringen, sie vereinfachen bzw. verringern den Wartungsaufwand und sie machen Software leichter erweiterbar. Außerdem sollen sie helfen, Seiteneffekte zu verringern und Abhängigkeiten untereinander zu entkoppeln, um auch da freier entwickeln zu können. Nun habe ich aber leider schon des Öfteren gesehen, dass Entwickler Patterns einsetzen, ohne sich genau damit beschäftigt zu haben. Man hat einfach ein besseres Gefühl, weil man glaubt, dass der Code allein durch den Einsatz von Patterns automatisch besser wird. Ob das Pattern auch wirklich für dieses Problem geeignet ist und ob da auch alle anderen Gegebenheiten stimmen, ist erst einmal nicht so wichtig, Hauptsache das Pattern wurde angewendet. Patterns sind eine feine Sache, aber immer und überall einfach so angewendet, können sie das Lesen des Codes erschweren und Strukturen schaffen, die die Software komplexer machen als eigentlich notwendig. Somit wird der Quellcode aufgeblähter und unter Umständen sogar fehleranfälliger.
Patterns sollten nicht angewendet werden, nur weil es wieder Zeit ist, irgendein Pattern einzusetzen. Quellcode, in dem 90 % aller Klassen ein Singleton sind, sollte meiner Meinung nach lieber noch einmal durchdacht und überarbeitet werden. Besonders häufig werden momentan das Strategy-Pattern oder auch das Observer-Pattern genutzt. Mit dem Observer-Pattern können viele einzelne Klienten benachrichtiget werden, wie es z. B. bei Events im .NET-Framework passiert. Es gibt natürlich noch viele weitere interessante Pattern, die unter anderem von der berühmt geworden gewordenen „GoF“, entwickelt und zusammengestellt wurden. Zur „GoF“ (Gang of Four) gehören vier Autoren (Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides), die in ihrem Buch wiederkehrende Muster in der Softwareentwicklung aufgelistet haben. Die folgende Tabelle von Entwurfsmustern enthält unter anderem Muster dieser Viererbande.
Erzeugende Muster |
Strukturelle Muster |
Verhaltensmuster |
Weitere Muster |
Abstract Factory |
Adapter |
Chain of Responsibility |
Business Delegate |
Builder |
Composite |
Command |
Data Access Object |
Factory Method |
Bridge |
Interpreter |
Data Transfer Object |
Prototype |
Decorator |
Iterator |
Dependency Injection |
Singleton |
Facade |
Mediator |
Inversion of Control |
|
Flyweight |
Memento |
Model View Controller |
|
Proxy |
Null Object |
Model View Presenter |
|
|
Observer |
Plug-in |
|
|
State |
Fluent Interface |
|
|
Strategy |
|
|
|
Template Method |
|
|
|
Visitor |
|
Auflistung unterschiedlichster Patterns