Die 7 wichtigsten Muster für das Software-Design

Um einen umfassenden Einblick in das Thema Software Design Patterns zu erhalten, lesen Sie Software Design Patterns: Best Practices für Entwickler, erstellt von C.H. Afzal, ein erfahrener Softwareentwickler mit mehrjähriger Erfahrung bei Netflix, Microsoft und Oracle. Ein Großteil des Folgenden ist aus seinem Kurs zusammengefasst.

Warum Entwurfsmuster?

Design Patterns sind in letzter Zeit zu einem Gegenstand einiger Kontroversen in der Programmierwelt geworden, hauptsächlich aufgrund ihrer wahrgenommenen Überbeanspruchung, die zu Code führt, der möglicherweise schwieriger zu verstehen und zu verwalten ist.

Es ist wichtig zu verstehen, dass Design Patterns niemals dazu gedacht waren, Shortcuts zusammen zu hacken, um sie nach dem Zufallsprinzip „one-size-fits-all“ für Ihren Code anzuwenden. Es gibt letztendlich keinen Ersatz für echte Problemlösungsfähigkeiten in der Softwareentwicklung.

Die Tatsache bleibt jedoch, dass Entwurfsmuster unglaublich nützlich sein können, wenn sie in den richtigen Situationen und aus den richtigen Gründen verwendet werden. Wenn sie strategisch eingesetzt werden, können sie einen Programmierer erheblich effizienter machen, indem sie es vermeiden, das sprichwörtliche Rad neu zu erfinden, anstatt Methoden zu verwenden, die bereits von anderen verfeinert wurden. Sie bieten auch eine nützliche gemeinsame Sprache, um wiederholte Probleme und Lösungen zu konzipieren, wenn Sie mit anderen diskutieren oder Code in größeren Teams verwalten.

Eine wichtige Einschränkung besteht jedoch darin, sicherzustellen, dass das Wie und Warum hinter jedem Muster auch vom Entwickler verstanden wird.

Ohne weiteres (in der Reihenfolge der Wichtigkeit von am wenigsten bis am wenigsten):

Die wichtigsten Designmuster

  1. Singleton

Das Singleton-Muster wird verwendet, um die Erstellung einer Klasse auf nur ein Objekt zu beschränken. Dies ist nützlich, wenn ein (und nur ein) Objekt erforderlich ist, um Aktionen im gesamten System zu koordinieren. Es gibt mehrere Beispiele, in denen nur eine einzige Instanz einer Klasse vorhanden sein sollte, einschließlich Caches, Thread-Pools und Registries.

Es ist trivial, ein Objekt einer Klasse zu initiieren - aber wie stellen wir sicher, dass immer nur ein Objekt erstellt wird? Die Antwort besteht darin, den Konstruktor für die Klasse, die wir als Singleton definieren möchten, "privat" zu machen. Auf diese Weise können nur die Mitglieder der Klasse und sonst niemand auf den privaten Konstruktor zugreifen.

Wichtige Überlegung: Es ist möglich, ein Singleton zu unterklassifizieren, indem der Konstruktor anstelle von privat geschützt wird. Dies kann unter Umständen geeignet sein. Ein Ansatz in diesen Szenarien besteht darin, ein Register von Singletons der Unterklassen zu erstellen, und die getInstance-Methode kann einen Parameter übernehmen oder eine Umgebungsvariable verwenden, um den gewünschten Singleton zurückzugeben. Die Registrierung verwaltet dann eine Zuordnung von Zeichenfolgennamen zu Singleton-Objekten, auf die bei Bedarf zugegriffen werden kann.

2. Fabrik Methode

Eine normale Fabrik produziert Waren; Eine Softwarefabrik produziert Objekte. Und nicht nur das - dies geschieht ohne Angabe der genauen Klasse des zu erstellenden Objekts. Zu diesem Zweck werden Objekte durch Aufrufen einer Factory-Methode anstelle eines Konstruktors erstellt.

Normalerweise läuft die Objekterstellung in Java folgendermaßen ab:

SomeClass someClassObject = new SomeClass ();

Das Problem mit dem obigen Ansatz ist, dass der Code, der das SomeClass-Objekt verwendet, plötzlich von der konkreten Implementierung von SomeClass abhängig wird. Es ist nichts Falsches daran, neue Objekte zu erstellen, aber es ist mit dem Gepäck verbunden, unseren Code eng an die konkrete Implementierungsklasse zu koppeln, was gelegentlich problematisch sein kann.

3. Strategie

Das Strategiemuster ermöglicht es, verwandte Algorithmen unter einer Abstraktion zu gruppieren, wodurch ein Algorithmus oder eine Richtlinie für einen anderen ausgetauscht werden kann, ohne den Client zu ändern. Anstatt einen einzelnen Algorithmus direkt zu implementieren, erhält der Code Laufzeitanweisungen, die angeben, welcher Algorithmus aus der Gruppe der auszuführenden Algorithmen ausgewählt werden soll.

4. Beobachter

Dieses Muster ist eine Eins-zu-Viele-Abhängigkeit zwischen Objekten, sodass alle abhängigen Objekte benachrichtigt werden, wenn ein Objekt den Status ändert. Dies erfolgt normalerweise durch Aufrufen einer ihrer Methoden.

Denken Sie der Einfachheit halber darüber nach, was passiert, wenn Sie jemandem auf Twitter folgen. Sie bitten Twitter im Wesentlichen, Ihnen (dem Beobachter) Tweet-Updates der Person (dem Betreff) zuzusenden, der Sie gefolgt sind. Das Muster besteht aus zwei Akteuren, dem Beobachter, der an den Aktualisierungen interessiert ist, und dem Subjekt, das die Aktualisierungen erzeugt.

Ein Thema kann viele Beobachter haben und ist eine Eins-zu-Viele-Beziehung. Ein Beobachter kann jedoch auch Updates von anderen Themen abonnieren. Sie können News-Feeds von einer Facebook-Seite abonnieren. Dies ist der Betreff. Wenn die Seite einen neuen Beitrag enthält, sieht der Abonnent den neuen Beitrag.

Wichtige Überlegung: Wenn bei vielen Probanden und wenigen Beobachtern jedes Proband seine Beobachter separat speichert, erhöhen sich die Speicherkosten, da einige Probanden denselben Beobachter mehrmals speichern.

5. Builder

Wie der Name schon sagt, wird ein Builder-Muster zum Erstellen von Objekten verwendet. Manchmal können die von uns erstellten Objekte komplex sein, aus mehreren Unterobjekten bestehen oder einen aufwändigen Konstruktionsprozess erfordern. Das Erstellen komplexer Typen kann mithilfe des Builder-Musters vereinfacht werden. Ein zusammengesetztes oder aggregiertes Objekt wird im Allgemeinen von einem Builder erstellt.

Wichtige Überlegung: Das Builder-Muster ähnelt möglicherweise dem Muster "Abstrakte Fabrik". Ein Unterschied besteht jedoch darin, dass das Builder-Muster schrittweise ein Objekt erstellt, während das Muster "Abstrakte Fabrik" das Objekt auf einmal zurückgibt.

6. Adapter

Auf diese Weise können inkompatible Klassen zusammenarbeiten, indem die Schnittstelle einer Klasse in eine andere konvertiert wird. Stellen Sie sich das als eine Art Übersetzer vor: Wenn sich zwei Staatschefs treffen, die keine gemeinsame Sprache sprechen, setzt sich in der Regel ein Dolmetscher zwischen die beiden und übersetzt das Gespräch, wodurch die Kommunikation ermöglicht wird.

Wenn Sie über zwei Anwendungen verfügen, von denen eine die Ausgabe als XML ausgibt und die andere eine JSON-Eingabe erfordert, benötigen Sie einen Adapter zwischen den beiden, damit sie reibungslos funktionieren.

7. Staat

Das Statusmuster kapselt die verschiedenen Status, in denen sich eine Maschine befinden kann, und ermöglicht es einem Objekt, sein Verhalten zu ändern, wenn sich der interne Status ändert. Die Maschine oder der Kontext, wie er im Pattern-Speak genannt wird, kann Aktionen ausführen, die sie in verschiedene Zustände treiben. Ohne die Verwendung des Musters wird der Code unflexibel und mit If-else-Bedingungen übersät.

Willst du weiter lernen?

Mit Software Design Patterns: Best Practices für Entwickler haben Sie die Möglichkeit, mehr als nur die Theorie zu lesen. Sie werden in der Lage sein, tief in echte Probleme einzutauchen und praktische Lösungen anhand von Codebeispielen aus der Praxis zu verstehen.

Der Kurs basiert auf dem beliebten Buch der Viererbande, wird jedoch in einem interaktiven, leicht verdaulichen Format angeboten. Sie beherrschen die 23 berühmten Entwurfsmuster aus dem Buch interaktiv, lernen die richtigen Anwendungen der drei wichtigsten Entwurfsmustertypen (kreativ, strukturell und verhaltensorientiert) und lernen, diese Entwurfsmuster in Ihre eigenen Projekte einzubeziehen.

Schau es dir jetzt an.

Ursprünglich veröffentlicht auf blog.educative.io am 7. November 2018.