Heim  >  Artikel  >  Java  >  Detaillierte Einführung in 23 gängige Java-Designmuster

Detaillierte Einführung in 23 gängige Java-Designmuster

WBOY
WBOYnach vorne
2022-03-07 17:32:252838Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Java. Entwurfsmuster sind eine Reihe von Code-Entwurfserfahrungen, die wiederholt verwendet werden sollen. Der Zweck besteht darin, Code wiederzuverwenden und ihn für andere einfacher zu machen Ich hoffe, dass er für alle hilfreich ist, um ihn zu verstehen und sicherzustellen, dass er zuverlässig ist.

Detaillierte Einführung in 23 gängige Java-Designmuster

Empfohlene Studie: „Java-Tutorial

1. Übersicht über Designmuster:

1. Was ist Designmuster:

Designmuster sind eine Reihe von Code-Designerfahrungen, die wiederholt verwendet wurden Der Zweck besteht darin, den Code wiederzuverwenden, ihn für andere verständlicher zu machen und die Zuverlässigkeit des Codes sicherzustellen. Entwurfsmuster sind eine Win-Win-Situation für uns selbst, die Menschen und die Systeme. Sie machen das Schreiben von Code zu einem echten Engineering. Sie sind der Grundstein der Softwareentwicklung, genau wie die Bausteine ​​eines Gebäudes. Durch den sinnvollen Einsatz von Designmustern in Projekten können viele Probleme in der Realität perfekt gelöst werden. Jedes Muster beschreibt ein Problem, das um uns herum immer wieder auftritt, und ist daher der Grund dafür weit verbreitet. Im Allgemeinen werden Entwurfsmuster in drei Hauptkategorien unterteilt:

  • Kreative Muster: insgesamt 5: Factory-Methodenmuster, abstraktes Fabrikmuster, Singleton-Muster, Builder-Muster, Prototypmuster
  • Strukturelle Muster: insgesamt 7 Typen: Adapter Modus, Dekorationsmodus, Proxy-Modus, Bridge-Modus, Erscheinungsmodus, Kombinationsmodus, Fliegengewichtsmodus
  • Verhaltensmodus: Insgesamt 11 Typen: Strategiemodus, Vorlagenmethodenmodus, Beobachtermodus, Verantwortungskettenmodus, Zugriffsvermittlermodus, Vermittlermodus , Iteratormodus, Befehlsmodus, Statusmodus, Memomodus, Interpretermodus

Tatsächlich gibt es zwei Typen: Parallelmodus und Thread-Pool-Modus. Beschreiben Sie das Ganze mit einem Bild:

2 . Die sechs Prinzipien von Designmustern:

(1) Open-Close-Prinzip:

Das Open-and-Close-Prinzip bezieht sich darauf, offen für Erweiterungen und geschlossen für Änderungen zu sein. Beim Erweitern des Programms kann der ursprüngliche Code nicht geändert werden. Um diesen Effekt zu erzielen, müssen wir Schnittstellen oder abstrakte Klassen verwenden Prinzip, das sich auf Schnittstellenprogrammierung bezieht, die eher auf Abstraktion als auf Konkretheit beruht:

Das Liskov-Substitutionsprinzip ist nur dann der Grundstein für die Wiederverwendung, wenn die Basisklasse ersetzt werden kann Das System wird nicht beeinträchtigt, die Basisklasse kann wiederverwendet werden und die Unterklasse kann der Basisklasse auch neue Verhaltensweisen hinzufügen. Das Liskov-Substitutionsprinzip bedeutet also, dass überall dort, wo eine Basisklasse erscheinen kann, auch eine Unterklasse erscheinen muss.

           Das Liskov-Substitutionsprinzip ist eine Ergänzung zum „Öffnungs- und Schließprinzip“. Der Schlüsselschritt zur Verwirklichung des „Öffnungs- und Schließprinzips“ ist die Abstraktion, und die Vererbungsbeziehung zwischen der Basisklasse und der Unterklasse ist die konkrete Implementierung der Abstraktion , also das Liskov-Substitutionsprinzip Es ist eine Spezifikation spezifischer Schritte zur Erzielung einer Abstraktion.

(4) Schnittstellentrennungsprinzip:

Die Verwendung mehrerer isolierter Schnittstellen ist besser als die Verwendung einer einzelnen Schnittstelle, wodurch die Kopplung und Abhängigkeit zwischen Schnittstellen verringert wird und die Aktualisierung und Wartung einfacher wird.

(5) Demeter-Prinzip:

Das Demeter-Prinzip, auch als am wenigsten bekanntes Prinzip bekannt, bedeutet, dass eine Klasse die Interaktionen mit anderen Entitäten minimieren sollte, wodurch die Funktionsmodule des Systems relativ unabhängig werden und Kopplungsbeziehungen reduziert werden. Die ursprüngliche Absicht dieses Prinzips besteht darin, die Kopplung von Klassen zu reduzieren. Obwohl die Kommunikation mit indirekten Klassen vermieden werden kann, muss die Kommunikation über einen „Vermittler“ erfolgen. Eine übermäßige Verwendung des Demeter-Prinzips führt zu einer großen Anzahl von Vermittlern und Klassen größere Systemkomplexität, daher müssen Sie bei der Verwendung des Dimit-Gesetzes wiederholt die Kompromisse abwägen, um sowohl eine klare Struktur als auch eine hohe Kohäsion und eine geringe Kopplung zu erreichen.

(6) Prinzip der zusammengesetzten Wiederverwendung:

Versuchen Sie, Kombination/Aggregation anstelle von Vererbung zu verwenden.

2. Die 23 Entwurfsmuster von Java:

Als nächstes werden wir die Konzepte, Anwendungsszenarien usw. der 23 Entwurfsmuster in Java im Detail vorstellen und sie anhand ihrer Eigenschaften und der Prinzipien der Entwurfsmuster analysieren

1 . Typ-Factory-Methodenmuster erstellen:

Factory-Methodenmuster ist in drei Typen unterteilt:

(1) Einfaches Factory-Muster:

Erstellen Sie eine Factory-Klasse und definieren Sie eine Schnittstelle, um Produktklassen zu erstellen, die dieselbe Schnittstelle implementieren. Schauen Sie sich zunächst das Beziehungsdiagramm an:

(2) Factory-Methodenmuster:

Das Factory-Methodenmuster ist eine Verbesserung gegenüber dem einfachen Factory-Muster „Öffnungs- und Schließprinzip“. Jedes Mal, wenn eine neue Produktklasse erstellt wird, ist eine Änderung der Fabrikklasse erforderlich, was der Systemerweiterung und -wartung nicht förderlich ist. Die Factory-Methode abstrahiert die Factory und definiert eine Schnittstelle zum Erstellen von Objekten. Jedes Mal, wenn Sie ein neues Produkt hinzufügen, müssen Sie nur das Produkt und die entsprechende spezifische Implementierungs-Factory-Klasse hinzufügen. Die spezifische Factory-Klasse bestimmt, welches Produkt instanziiert werden soll, und verzögert die Erstellung und Instanziierung des Objekts in der Unterklasse Das Design der Fabrik entspricht dem „Öffnungs- und Schließprinzip“. Beim Erweitern muss der ursprüngliche Code nicht geändert werden. Das UML-Beziehungsdiagramm lautet wie folgt:

(3) Statisches Factory-Methodenmuster:

Das statische Factory-Muster macht die Methoden im Factory-Methodenmuster statisch. Es ist nicht erforderlich, eine Instanz zu erstellen, sondern nur aufzurufen es direkt.

Detaillierter Artikel zum Factory-Methodenmuster: Erstellungstyp des Java-Designmusters: Detaillierte Erklärung des Factory-Musters (einfache Factory + Factory-Methode + abstrakte Factory)

2. Erstellungstyp – abstraktes Factory-Muster:

Die Zusammenfassung Factory-Muster werden hauptsächlich zum Erstellen von Familien verwandter Objekte verwendet. Wenn eine Produktfamilie so gestaltet werden muss, dass sie zusammenarbeitet, kann das abstrakte Factory-Muster sicherstellen, dass der Client immer nur Objekte derselben Produktfamilie verwendet. Durch die Isolierung der Generierung spezifischer Klassen muss der Client die spezifischen Klassen nicht explizit angeben Generation. Alle konkreten Fabriken implementieren die in der abstrakten Fabrik definierte öffentliche Schnittstelle, sodass Sie nur die Instanz der konkreten Fabrik ändern müssen, um das Verhalten des gesamten Softwaresystems in gewissem Maße zu ändern.

Der Nachteil dieses Modells besteht jedoch darin, dass das Hinzufügen neuer Verhaltensweisen schwieriger ist. Wenn Sie ein neues Produktfamilienobjekt hinzufügen müssen, müssen Sie die Schnittstelle und alle ihre Unterklassen ändern, was zwangsläufig große Probleme verursacht.

Das UML-Strukturdiagramm sieht wie folgt aus:

Details zum abstrakten Fabrikmuster: Erstellungstyp des Java-Entwurfsmusters: Detaillierte Erläuterung des Fabrikmusters (einfache Fabrik + Fabrikmethode + abstrakte Fabrik)

3 Typ - Builder-Muster:

                                                                                                                                       Das Builder-Muster zerlegt die Erstellungsschritte komplexer Produkte in verschiedene Methoden, wodurch der Erstellungsprozess klarer wird und somit der Erstellungsprozess komplexer Objekte präziser gesteuert werden kann , die Erstellung von Produkten Unabhängig vom Produkt selbst können im selben Bauprozess unterschiedliche Objekte erstellt werden, und jeder Betonbauer ist unabhängig voneinander, sodass es einfach ist, den Betonbauer zu ersetzen oder einen neuen Betonbauer hinzuzufügen, und Benutzer verwenden unterschiedliche Betonbauer können dann unterschiedliche Produktobjekte erhalten. Das UML-Strukturdiagramm sieht wie folgt aus:

Details zum Builder-Muster: Erstellungstyp des Java-Entwurfsmusters: Builder-Muster

4. Erstellungstyp – Singleton-Modus:

Der Singleton-Modus kann sicherstellen, dass a Bestimmte Eine Klasse hat nur eine Instanz. Die Klasse instanziiert sich selbst und stellt einen öffentlichen Zugangspunkt für diese Instanz zum gesamten System bereit. Mit Ausnahme dieses öffentlichen Zugangspunkts kann nicht auf andere Weise auf die Instanz zugegriffen werden. Die Vorteile des Singleton-Modus sind:

  • Es gibt nur ein gemeinsam genutztes Instanzobjekt im System. Es ist nicht erforderlich, häufig Objekte zu erstellen und zu zerstören, was Systemressourcen spart und die Systemleistung verbessert.
  • Kann streng kontrolliert werden Kunden greifen auf das Singleton-Objekt zu.

Es gibt verschiedene Möglichkeiten, das Singleton-Muster zu schreiben. Es gibt drei Haupttypen: Singleton im Lazy-Man-Stil, Singleton im Hungrig-Man-Stil und Singleton im Registrierungsstil.

Details zum Singleton-Muster: Erstellungstyp des Java-Designmusters: Singleton-Muster

5. Erstellungstyp-Prototyp-Muster:

Das Prototyp-Muster wird auch für die Erstellung von Objekten verwendet Prototyp, der Es führt einen Kopier-Klon durch und erzeugt ein neues Objekt, das dem Quellobjekt ähnelt. Das UML-Klassendiagramm sieht wie folgt aus:

In Java ist der Kern des Prototypmusters die Prototypklasse Prototype. Die Prototypklasse muss die folgenden zwei Bedingungen erfüllen:

  • Implementieren Sie die Cloneable-Schnittstelle:
  • Überschreiben Sie die clone()-Methode in der Object-Klasse, um eine Kopie des Objekts zurückzugeben.

Die clone()-Methode in der Object-Klasse verwendet standardmäßig eine flache Kopie Kopieren des Objekts, dann müssen Sie Ihre eigene Kopierlogik in der clone()-Methode anpassen.

  • Flache Kopie: Nach dem Kopieren eines Objekts werden die Variablen des Basisdatentyps neu erstellt und der Referenztyp zeigt weiterhin auf die Speicheradresse, auf die das ursprüngliche Objekt zeigt.
  • Tiefe Kopie: Nachdem ein Objekt kopiert wurde, werden sowohl grundlegende Datentypen als auch Referenztypen neu erstellt.

Die Verwendung des Prototypmodus zum Erstellen von Objekten vereinfacht nicht nur die Schritte zur Objekterstellung, sondern bietet auch eine viel bessere Leistung als das Erstellen von Objekten mit der neuen Methode, da die clone()-Methode der Object-Klasse eine lokale Methode ist, die das direkt ausführt Binärstrom im Speicher, insbesondere beim Kopieren großer Objekte, ist der Unterschied in der Leistung sehr offensichtlich; Die nächsten 7 Strukturen Typmodi: Adaptermodus, Dekorationsmodus, Proxy-Modus, Erscheinungsmodus, Brückenmodus, Kombinationsmodus, Fliegengewichtsmodus. Der Adaptermodus des Objekts ist der Ursprung verschiedener Modi, wie unten gezeigt:

6, strukturierter Adaptermodus:

Der Adaptermodus wird hauptsächlich zum Konvertieren einer Klasse oder Schnittstelle in das Format der Client-Hoffnung verwendet. Damit die ursprünglichen inkompatiblen Klassen zusammenarbeiten können, um die Zielklasse und die Adapterklasse zu entkoppeln, entspricht es auch dem „Öffnungs- und Schließprinzip“, und neue Adapterklassen können hinzugefügt werden, ohne den ursprünglichen Code zu ändern Die Adapterklasse ist für die Clientklasse transparent und verbessert die Wiederverwendbarkeit des Adapters. Der Nachteil besteht jedoch darin, dass der Implementierungsprozess zum Ersetzen des Adapters relativ kompliziert ist.

Daher eignet sich das Adaptermuster besser für die folgenden Szenarien:

(1) Das System muss vorhandene Klassen verwenden und die Schnittstellen dieser Klassen entsprechen nicht den Schnittstellen des Systems.

(2) Bei Verwendung von Komponenten von Drittanbietern unterscheidet sich die Definition der Komponentenschnittstelle von Ihrer eigenen Definition. Sie möchten Ihre eigene Schnittstelle nicht ändern, sondern müssen die Funktionen der Komponentenschnittstelle von Drittanbietern verwenden.

    Das Folgende ist ein sehr anschauliches Beispiel, das veranschaulicht, was das Adaptermuster ist:
Es gibt drei Hauptimplementierungen des Adaptermusters: Klassenadaptermuster, Objektadaptermuster und Schnittstellenadaptermuster. Die Verwendungsszenarien der drei sind wie folgt:

Klassenadaptermuster: Wenn Sie eine Klasse in eine Klasse konvertieren möchten, die eine andere neue Schnittstelle erfüllt, können Sie das Klassenadaptermuster verwenden, um eine neue Klasse zu erstellen und die ursprüngliche Klasse zu erben , und implementieren Sie einfach eine neue Schnittstelle.

Objektadaptermuster: Wenn Sie ein Objekt in ein Objekt konvertieren möchten, das eine andere neue Schnittstelle erfüllt, können Sie eine Wrapper-Klasse erstellen und in der Methode der Wrapper-Klasse einfach die Instanzmethode aufrufen .

Adaptermuster der Schnittstelle: Wenn Sie nicht alle Methoden in einer Schnittstelle implementieren möchten, können Sie einen abstrakten Klassen-Wrapper erstellen, um alle Methoden zu implementieren. Wenn wir andere Klassen schreiben, können wir einfach die abstrakte Klasse erben.
  • Details zum Adaptermuster: Strukturtyp von Java-Entwurfsmustern: Adaptermuster
  • 7. Strukturtyp - Dekoratormuster:
Das Dekoratormuster kann dem Objekt dynamisch einige zusätzliche Verantwortlichkeiten hinzufügen, um die Funktionalität zu erweitern Verschiedene Dekoratoren zur Laufzeit können unterschiedliche Verhaltensweisen erzielen. Durch die Anordnung und Kombination verschiedener Dekorationsklassen können Sie viele verschiedene Verhaltensweisen erstellen und dem „Öffnungs- und Schließprinzip“ entsprechen Die Klasse und die dekorierte Klasse ändern sich unabhängig voneinander. Benutzer können nach Bedarf neue dekorierte Klassen und dekorierte Klassen hinzufügen und diese dann kombinieren, wenn sie verwendet werden. Der ursprüngliche Code muss nicht geändert werden. Das UML-Strukturdiagramm des Dekoratormusters lautet wie folgt:

Das Dekoratormuster weist jedoch auch Mängel auf. Erstens werden viele kleine Objekte generiert, was die Komplexität des Systems erhöht Bei mehreren Dekorationsobjekten kann das Auffinden von Fehlern während des Debuggens eine schrittweise Fehlerbehebung erfordern, was umständlich ist.

Details zum Dekoratormuster: Strukturtyp des Java-Entwurfsmusters: Dekoratormuster

8. Strukturelles Proxy-Muster:

Die Designmotivation des Proxy-Musters besteht darin, über das Proxy-Objekt auf das reale Objekt zuzugreifen. Durch die Einrichtung einer Objekt-Proxy-Klasse steuert das Proxy-Objekt die Referenz des ursprünglichen Objekts und realisiert so das Betrieb des realen Objekts. Im Proxy-Modus spielt das Proxy-Objekt hauptsächlich die Rolle eines Vermittlers, der zur Koordinierung und Verbindung des Anrufers (d. h. des Clients) und des Angerufenen (d. h. des Zielobjekts) verwendet wird, wodurch die Kopplung des Systems und auch des Ziels bis zu einem gewissen Grad reduziert wird Objekt geschützt. Der Nachteil besteht jedoch darin, dass zwischen dem Anrufer und dem Angerufenen ein Proxy-Objekt hinzugefügt wird, was die Verarbeitung von Anforderungen verlangsamen kann. Das UML-Strukturdiagramm sieht wie folgt aus:

Details zum Proxy-Muster: Strukturtyp des Java-Entwurfsmusters: Proxy-Muster

9. Strukturtyp - Brückenmuster:

Das Brückenmuster trennt und entkoppelt die Zusammenfassung Teil des Systems vom Implementierungsteil getrennt, so dass sie sich unabhängig voneinander ändern können. Um den Zweck zu erreichen, dass sich der abstrakte Teil und der Implementierungsteil unabhängig voneinander ändern können, verwendet der Brückenmodus eine Kombinationsbeziehung anstelle einer Vererbungsbeziehung. Der abstrakte Teil verfügt über ein Schnittstellenobjekt des Implementierungsteils, sodass die Funktionen des Über dieses Schnittstellenobjekt kann ein spezifischer Implementierungsteil aufgerufen werden. Mit anderen Worten, die Brücke im Brückenmodus ist eine einseitige Beziehung, und nur der abstrakte Teil kann die Objekte des Implementierungsteils verwenden, nicht jedoch umgekehrt.

                        Der Bridge-Modus entspricht dem „Öffnungs- und Schließprinzip“, wodurch eine der beiden sich ändernden Dimensionen beliebig erweitert werden kann, ohne dass das ursprüngliche System geändert werden muss Details zur Implementierung. Da die Aggregationsbeziehung jedoch auf der Abstraktionsebene hergestellt wird, müssen Entwickler für die Abstraktion programmieren, was das Verständnis und die Gestaltung des Systems erschwert. Das UML-Strukturdiagramm des Bridge-Modus lautet wie folgt:

Wenn wir JDBC zum Herstellen einer Verbindung zur Datenbank verwenden, müssen wir grundsätzlich nicht zu viel Code verschieben Der Grund dafür ist, dass der Bridge-Modus verwendet wird. JDBC stellt eine einheitliche Schnittstelle bereit, jede Datenbank stellt ihre eigene Implementierung bereit und die Bridge-Klasse erstellt dann einen Treiber für die Verbindung mit der Datenbank. Bei Verwendung einer bestimmten Datenbank muss nur gewechselt werden. Das Strukturdiagramm von JDBC lautet wie folgt:

In JDBC ist die Implementierungsrolle (Implementor) des Bridge-Modus die Treiberschnittstelle, die konkrete Implementierungsrolle (Concrete Implementor) entspricht MysqlDriver, OracleDriver und MariadbDriver und die Die erweiterte Abstraktionsrolle (Refined Abstraction) entspricht DriverManager und verfügt nicht über eine Abstraktionsrolle (Abstraction) als übergeordnete Klasse der erweiterten Abstraktionsrolle.情 Details zum Bridge-Modus: Strukturtyp des Java-Designmodus: Bridge-Modus

10, Struktureller Form-Darstellungsmodus:

Der Darstellungsmodus bietet dem Client eine einheitliche Schnittstelle für den Zugriff auf eine Gruppe von Schnittstellen im Subsystem. Die Verwendung des Darstellungsmodus hat folgende Vorteile:

(1) Einfacher zu verwenden: Dadurch ist das Subsystem einfacher zu verwenden. Der Client muss die interne Implementierung des Subsystems nicht mehr verstehen und auch nicht mit den internen Modulen interagieren von vielen Subsystemen. Sie müssen nur mit der Erscheinungsklasse interagieren.

(2) Lose Kopplung: Entkoppeln Sie den Client vom Subsystem, was die Erweiterung und Wartung von Modulen innerhalb des Subsystems erleichtert.

(3) Bessere Aufteilung der Zugriffsebenen: Durch den sinnvollen Einsatz von Facade können die Zugriffsebenen besser aufgeteilt werden. Einige Methoden sind außerhalb des Systems und einige Methoden werden intern innerhalb des Systems verwendet. Konzentrieren Sie die Funktionen, die nach außen sichtbar sein müssen, in der Fassade, was nicht nur für den Kunden praktisch ist, sondern auch die internen Details gut verbirgt.

Wenn das Erscheinungsmuster den Subsystemklassen jedoch zu viele Einschränkungen auferlegt, verringert es die Variabilität und Flexibilität. Daher eignet sich das Erscheinungsmuster zur Bereitstellung einer einfachen Schnittstelle für komplexe Subsysteme, zur Verbesserung der Benutzerfreundlichkeit des Systems und zur Einführung des Erscheinungsbilds Das Subsystem ist vom Client entkoppelt, um die Unabhängigkeit und Portabilität des Subsystems zu verbessern.

Das UML-Strukturdiagramm des Erscheinungsmusters lautet wie folgt:

Details zum Erscheinungsmuster: Strukturtyp des Java-Entwurfsmusters: Erscheinungsmuster

11. Struktureller Kombinationsmodus:

              Der Kombinationsmodus kombiniert Blattobjekte und Containerobjekte rekursiv, um eine Baumstruktur zu bilden, die die „Teil-Ganze“-Struktur darstellt, sodass Benutzer problemlos einzelne Objekte und kombinierte Objekte verwenden können , die Fähigkeit, zusammengesetzte Objekte ohne Unterscheidung wie Blattobjekte zu behandeln, ermöglicht die Entkopplung von Benutzerprogrammen von der internen Struktur komplexer Elemente.

Das Wichtigste am Kombinationsmodus ist, dass Blattobjekte und Kombinationsobjekte dieselbe abstrakte Konstruktionsklasse implementieren. Kunden müssen nur für diese abstrakte Konstruktionsklasse programmieren . Der Grund, warum Blattknoten und Objektknoten konsistent verarbeitet werden können. Das UML-Strukturdiagramm des Kombinationsmusters lautet wie folgt:

Details des Kombinationsmusters: Strukturtyp des Java-Entwurfsmusters: Kombinationsmuster

12. Strukturtyp-Fliegengewichtsmuster:

Das Fliegengewichtsmuster ist Effektive Unterstützung durch Sharing-Technologie. Fein abgestimmte Objektwiederverwendung mit kleinen Zustandsänderungen. Wenn es mehrere identische Objekte im System gibt, ist es nicht notwendig, für jedes Objekt ein Objekt zu instanziieren im System und spart so Ressourcen.

    Der Kern des Flyweight-Modells ist die Flyweight-Factory-Klasse. Wenn der Client ein Objekt benötigt, ruft er es zunächst aus dem Flyweight-Pool ab , es kehrt direkt zurück. Wenn es nicht im Flyweight-Pool vorhanden ist, erstellen Sie eine neue Flyweight-Objektinstanz, geben Sie sie an den Benutzer zurück und speichern Sie das neue Objekt im Flyweight-Pool, was die Bedeutung eines Singletons hat.

            Factory-Klassen verwenden normalerweise Sammlungstypen zum Speichern von Objekten wie HashMap, Hashtable, Vector usw. In Java sind Datenbankverbindungspools, Thread-Pools usw. alle Anwendungen, die das Flyweight-Muster verwenden.

              Das UML-Strukturdiagramm des Fliegengewichtsmusters lautet wie folgt:                                                    ' s ' s ' s t t                  Die Zeichenfolgenkonstanten von Java werden im Zeichenfolgenkonstantenpool gespeichert, und die JVM stellt sicher, dass sich nur eine Kopie einer Zeichenfolgenkonstante im Konstantenpool befindet.

Und wenn es um gemeinsam genutzte Pools geht, können wir uns leicht den JDBC-Verbindungspool in Java vorstellen. Durch die Verwaltung des Verbindungspools wird die gemeinsame Nutzung von Datenbankverbindungen realisiert, und die Verbindung muss nicht jedes Mal neu erstellt werden Zeit sparen, Kosten für die Neuerstellung der Datenbank einsparen und die Leistung des Systems verbessern.

Details zum Flyweight-Muster: Strukturtyp des Java-Designmusters: Flyweight-Muster

Zuvor haben wir 7 strukturelle Designmuster eingeführt, als nächstes stellen wir 11 Verhaltensdesignmuster vor: Strategiemuster, Vorlagenmethodenmuster, Beobachtermuster, Iteratormuster, Kette Verantwortungsmuster, Befehlsmuster, Memomuster, Zustandsmuster, Besuchermuster, Vermittlermuster, Dolmetschermuster. Machen wir zunächst ein Bild, um die Beziehung zwischen diesen 11 Mustern zu sehen:

13. Verhaltensstrategiemuster:

Extrahieren Sie die sich häufig ändernden oder möglicherweise ändernden Teile der Klasse als abstrakte Strategieschnittstellenklasse und verwenden Sie dann die Die Klasse enthält eine Instanz dieses Objekts, sodass die Klasseninstanz das Verhalten der Klasse, die diese Schnittstelle implementiert, zur Laufzeit frei aufrufen kann.

                        Zum Beispiel eine Reihe von Algorithmen zu definieren, jeden Algorithmus zu kapseln und sie austauschbar zu machen, sodass sich der Algorithmus unabhängig von den Kunden ändern kann, die ihn verwenden, das ist das Strategiemuster. Das UML-Strukturdiagramm sieht wie folgt aus:

Der Vorteil des Strategiemusters besteht darin, dass es das Verhalten des Objekts dynamisch ändern kann, der Nachteil besteht jedoch darin, dass viele Strategieklassen generiert werden und die Entscheidungsbefugnis von Das Strategiemuster liegt beim Benutzer. Das System stellt nur die Implementierung verschiedener Algorithmen bereit, daher muss Duan alle Strategieklassen kennen und selbst entscheiden, welche Strategieklasse verwendet wird.

Der Strategiemodus ist für die folgenden Szenen anwendbar:

  • (1) Die Anwendung muss bestimmte funktionale Dienste implementieren, und das Programm verfügt über mehrere Implementierungsmethoden, daher muss es dynamisch einen von mehreren Algorithmen auswählen
  • (2) Eine Klasse definiert mehrere Verhaltensalgorithmen. Und wenn diese Verhaltensweisen auftreten In Form mehrerer bedingter Anweisungen in der Operation der Klasse können die relevanten bedingten Zweige in ihre jeweiligen Strategieklassen verschoben werden, um diese bedingten Anweisungen zu ersetzen.

Details zum Strategiemuster: Verhaltensorientiertes Java-Entwurfsmuster

14. Die Vorlagenmethode wird basierend auf der Vererbung und den Ausführungsschritten implementiert des Algorithmus (d. h. das Algorithmusgerüst) werden in der Vorlagenmethode definiert. Im Vorlagenmethodenmuster können die gemeinsamen Teile der Unterklasse in der übergeordneten Klasse implementiert werden, während die charakteristischen Teile in der Unterklasse verzögert werden. Sie müssen lediglich den charakteristischen Teil als abstrakte Methode in der übergeordneten Klasse deklarieren Unterklasse Bestimmte Schritte im Algorithmus können neu definiert werden, ohne die Algorithmusstruktur zu ändern, und verschiedene Unterklassen können diese Logik auf unterschiedliche Weise implementieren.

Der Vorteil des Vorlagenmethodenmusters besteht darin, dass es dem „Öffnungs- und Schließprinzip“ entspricht und auch eine Wiederverwendung von Code erreichen, unverändertes Verhalten auf die übergeordnete Klasse übertragen und doppelten Code in der Unterklasse entfernen kann. Der Nachteil besteht jedoch darin, dass unterschiedliche Implementierungen eine Unterklasse definieren müssen, was zu einer Erhöhung der Anzahl der Klassen führt, wodurch das System größer und das Design abstrakter wird. Das UML-Diagramm des Vorlagenmethodenmusters lautet wie folgt:

Vorlagenmethodendetails: Verhaltenstyp des Java-Entwurfsmusters: Vorlagenmethodenmuster

15. Verhaltensketten-des-Verantwortungsmodell:

Die Verantwortungskette kann den Bearbeiter der Anfrage zuweisen. In einer Kette organisieren und die Anfrage entlang der Kette weiterleiten. Wenn ein Bearbeiter die Anfrage bearbeiten kann, wird sie verarbeitet, andernfalls wird die Anfrage an den Vorgesetzten zur Bearbeitung übergeben. Der Client muss die Anfrage nur an die Verantwortungskette senden und muss nicht auf die Details der Anfrageverarbeitung achten. Der Absender und Prozessor der Anfrage sind durch die Verantwortungskette entkoppelt.

          Das Chain-of-Responsibility-Muster kann die Verbindung zwischen Objekten vereinfachen, da weder der Auftraggeber noch der Auftragsverarbeiter klare Informationen über die jeweils andere Partei haben und der Auftragsverarbeiter die Struktur in der Verantwortungskette nicht kennt. Der Auftragsverarbeiter muss lediglich eine Referenz speichern B. an den Nachfolger, Es ist nicht erforderlich, Referenzen zu allen Kandidaten zu speichern.

Darüber hinaus erhöht das Chain-of-Responsibility-Modell die Flexibilität des Systems. Wir können Bearbeiter nach Belieben hinzufügen oder ändern und sogar die Reihenfolge der Bearbeiter ändern. Dies kann jedoch dazu führen, dass eine Anfrage trotzdem nicht bearbeitet wird am Kettenende platziert werden.

Das Verantwortungskettenmodell hat also folgende Vorteile:

(1) Reduzieren Sie den Grad der Kopplung und entkoppeln Sie Sender und Empfänger der Anfrage. Im Code ist es nicht nötig, viele hässliche if...else-Anweisungen in der Klasse zu schreiben. Wenn die Verantwortungskette verwendet wird, ist dies gleichbedeutend mit einer Blackbox. Wir müssen nur die Anfrage einreichen zu einem der Prozessoren und lassen Sie dann die Blackbox hineingehen. Seien Sie einfach für die Lieferung verantwortlich.
  • (2) Vereinfacht das Objekt, sodass das Objekt keine Kettenstruktur benötigt.
  • (3) Erhöhen Sie die Flexibilität des Systems, indem Sie das dynamische Hinzufügen oder Löschen von Handlern ermöglichen, indem Sie Mitglieder innerhalb der Kette ändern oder ihre Reihenfolge verschieben.
  • (4) Es ist praktisch, neue Anforderungsverarbeitungsklassen hinzuzufügen.
  • Aber das Chain-of-Responsibility-Modell weist auch einige Mängel auf:

(1) Es gibt keine Garantie dafür, dass die Anfrage erfolgreich verarbeitet wird.
  • (2) Die Systemleistung wird bis zu einem gewissen Grad beeinträchtigt, und es kann zu Schleifenaufrufen kommen geschehen.
  • (3) Es ist möglicherweise nicht einfach, die Laufzeiteigenschaften zu beobachten, und es ist beim Debuggen des Codes unpraktisch, was das Debuggen behindert.
Das UML-Strukturdiagramm des Chain-of-Responsibility-Musters lautet wie folgt:

Details des Chain-of-Responsibility-Musters: Verhaltenstyp des Java-Entwurfsmusters: Chain-of-Responsibility-Muster

16. Beobachtermuster:

Beobachtermuster, auch bekannt als Publish-Subscribe-Muster, definiert eine Eins-zu-Viele-Abhängigkeitsbeziehung zwischen Objekten. Wenn sich der Zustand des Zielobjekts (Beobachters) ändert, werden alle seine Abhängigkeiten (Beobachter) geändert benachrichtigt. Ein Beobachtungsziel kann mehreren Beobachtern entsprechen, und diese Beobachter sind nicht miteinander verbunden, sodass Beobachter nach Bedarf hinzugefügt und gelöscht werden können, was die Erweiterung des Systems und die Einhaltung des Öffnungs- und Schließprinzips erleichtert Zielobjekt und Beobachtung Die Beobachter sind zwar lose miteinander verbunden, können aber dennoch interagieren. Das Zielobjekt kennt nur eine bestimmte Beobachterliste Sie alle haben eine gemeinsame Schnittstelle.

 Der Nachteil des Beobachtermusters besteht jedoch darin, dass es bei vielen Beobachtern eine gewisse Zeit dauert, alle Beobachter zu benachrichtigen. Wenn eine zirkuläre Abhängigkeit zwischen dem Beobachter und dem Beobachteten besteht, kann dies zum Absturz des Systems führen. und Das Beobachtermuster verfügt nicht über einen entsprechenden Mechanismus, mit dem der Beobachter wissen kann, wie sich das beobachtete Objekt geändert hat, sondern nur, um zu wissen, dass sich das Beobachtungsziel geändert hat. Das UML-Strukturdiagramm des Beobachtermusters lautet wie folgt:

Beobachtermusterdetails: Verhaltensorientiertes Java-Entwurfsmuster: Beobachtermuster

17. Verhaltens-Besuchermuster:

Besuchermuster ist eine Methode zum Trennen von Objekten Datenstruktur und Verhalten (Operationen basierend auf Datenstrukturen) wird der Effekt des dynamischen Hinzufügens neuer Operationen zu einem Besucher erzielt, sodass neue Operationen hinzugefügt werden können, die auf diese Datenstrukturen wirken Es ist nicht erforderlich, jede Datenstruktur zu ändern. Es bietet mehrere Zugriffsmethoden für verschiedene Arten von Datenstrukturen.

Sie können nicht nur das Hinzufügen neuer Zugriffsvorgänge vereinfachen, sondern auch die Vorgänge der Klassenhierarchie definieren, ohne die vorhandene Klassenhierarchie zu ändern, und das Zugriffsverhalten verwandter Elementobjekte in einem Besucherobjekt konzentrieren, anstatt sie zu verteilen nacheinander in Elementklassen.

Der Nachteil des Besuchermusters besteht jedoch darin, dass es schwierig ist, neue Elementklassen hinzuzufügen. Jedes Hinzufügen einer neuen Elementklasse bedeutet das Hinzufügen einer neuen abstrakten Operation zur Rolle des abstrakten Besuchers und das Hinzufügen einer neuen abstrakten Operation für jeden einzelnen Besucher . Das Hinzufügen entsprechender spezifischer Operationen zur Klasse verstößt gegen die Anforderungen des „Öffnungs- und Schließprinzips“

Daher eignet sich das Besuchermuster für Systeme, die die Objektstruktur selten ändern, aber häufig neue Operationen für diese Objektstruktur definieren müssen Das Hinzufügen von Operationen durch den Algorithmus wird einfach. Oder es ist notwendig, viele verschiedene und nicht zusammenhängende Operationen an einer Objektstruktur auszuführen, und es ist notwendig, eine Verschmutzung dieser Objekte durch diese Operationen zu vermeiden, und möchte diese Klassen nicht ändern, wenn neue Operationen hinzugefügt werden .

                                                                                   ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s ’ s , hauptsächlich zum Deklarieren einiger Operationen; Objektstruktur ObjectStructure dient als Brücke zwischen den beiden und speichert verschiedene Arten von Objekten, sodass verschiedene Besucher darauf zugreifen können und derselbe Besucher auf unterschiedliche Weise auf verschiedene Elemente zugreifen kann, sodass das Hinzufügen neuer Besucher im Besuchermodus keine Änderung der vorhandenen erfordert Code und kann erweitert werden.式 Die Dual-Distribution-Technologie wird im Besuchermodus verwendet. Die sogenannte Double-Point-Technologie berücksichtigt bei der Auswahl einer Methode nicht nur den Laufzeitunterschied des Nachrichtenempfängers, sondern auch den Unterschied zwischen der Laufzeit der Parameter. Im Besuchermodus übergibt der Client den spezifischen Status als Parameter an den spezifischen Besucher. Der erste Versand wird hier abgeschlossen, und dann wird der spezifische Besucher als Parameter in der Methode „Spezifischer Status“ verwendet, und dieser ist ebenfalls vorhanden Als Parameter übergeben, wird hier der zweite Versand abgeschlossen. Doppelter Versand bedeutet, dass die resultierende Ausführung von der Art der Anfrage und der Art des Empfängers abhängt.

Details zum Besuchermuster: Verhaltens-Java-Designmuster: Besuchermuster

18.      use                   use     ’ ’ ’ use ’ s ’ s t-- t-to Das komplexe Beziehungsnetzwerk Die Struktur zwischen Objekten wird zu einer einfachen Sternstruktur mit dem Vermittler als Kern, und die Eins-zu-Viele-Assoziation zwischen Objekten wird in eine Eins-zu-Eins-Assoziation umgewandelt, wodurch die Beziehung zwischen Objekten vereinfacht und das Verständnis zwischen ihnen erleichtert wird Objekt Die Beziehung ist entkoppelt und jedes Objekt interagiert nicht mehr direkt mit den zugehörigen Objekten, sondern kommuniziert mit den zugehörigen Objekten über das Zwischenobjekt, sodass die Objekte relativ unabhängig verwendet werden können, was die Wiederverwendbarkeit der Objekte und die Skalierbarkeit des Systems verbessert.

Im Mediatormuster steht die Mediatorklasse im Mittelpunkt. Sie kapselt nicht nur die Beziehung zwischen Objekten, sondern kann auch die Interaktion zwischen Objekten weiter steuern. Das UML-Strukturdiagramm des Mediatormusters lautet wie folgt:

         Das Vermittlerobjekt kapselt jedoch die Beziehung zwischen Objekten, was dazu führt, dass das Vermittlerobjekt größer und komplexer wird, mehr Verantwortung trägt und schwieriger zu warten ist. Die Interaktionsdetails müssen bekannt sein Wenn etwas schief geht, wird das gesamte System schiefgehen.

Details zum Mediator-Muster: Verhaltens-Java-Entwurfsmuster: Mediator-Muster

19. Das Wesentliche des Befehlsmusters besteht darin, Anfragen in Objekte zu kapseln und die Verantwortung für die Ausgabe und Ausführung von Befehlen zuzuweisen. Unabhängig davon sind der Absender und der Empfänger des Befehls vollständig entkoppelt. Der Absender muss nur wissen, wie er den Befehl sendet, und muss sich nicht darum kümmern, wie der Befehl implementiert wird oder ob er erfolgreich ausgeführt wird. Der Schlüssel zum Befehlsmodus ist die Einführung einer abstrakten Befehlsschnittstelle. Dem Empfänger können nur bestimmte Befehle zugeordnet werden, die die abstrakte Befehlsschnittstelle implementieren.

Der Vorteil der Verwendung des Befehlsmodus besteht darin, dass die Kopplung des Systems verringert wird und neue Befehle problemlos zum System hinzugefügt werden können. Außerdem ist es einfach, einen kombinierten Befehl zu entwerfen. Der Nachteil besteht jedoch darin, dass einige Systeme zu viele spezifische Befehlsklassen haben, da für jeden Befehl eine bestimmte Befehlsklasse entworfen werden muss.

        Das UML-Strukturdiagramm des Befehlsmusters lautet wie folgt:

Befehlsmusterdetails: Verhaltenstyp des Java-Entwurfsmusters: Befehlsmodus

20. Verhaltenszustandsmodus:

                                                                                                                                                                                                                                         Wenn sich der Zustand ändert, sieht das Objekt so aus, als hätte es seine Klasse geändert, d. h. es hätte sein Verhalten mithilfe des Zustands als Atom geändert, anstatt den Zustand durch Verhalten zu ändern.

Wenn das Verhalten eines Objekts von seinen Attributen abhängt, nennen wir diese Attribute Zustand und das Objekt wird als Zustandsobjekt bezeichnet. Bei einem Statusobjekt hängt sein Verhalten von seinem Status ab. Wenn Sie beispielsweise ein Zimmer buchen möchten, können Sie es nur dann buchen, wenn das Zimmer frei ist ist kostenlos. Wenn bei einem solchen Objekt seine externen Ereignisse interagieren, ändert sich sein interner Zustand, wodurch sich auch sein Verhalten entsprechend ändert.

              Das UML-Strukturdiagramm des Zustandsmusters lautet wie folgt:

Aus dem UML-Strukturdiagramm oben können wir erkennen, dass die Vorteile des Zustandsmusters sind:

(1) Kapselt die Konvertierungsregeln und ermöglicht so die Die Zustandsumwandlungslogik muss in das Zustandsobjekt integriert werden, anstelle eines riesigen bedingten Anweisungsblocks

(2) Fassen Sie alle zustandsbezogenen Verhaltensweisen in einer Klasse zusammen, Sie können problemlos neue Zustände hinzufügen und müssen nur den Objektzustand ändern, um ihn zu ändern das Verhalten des Objekts.

Aber die Nachteile des Zustandsmusters sind:

(1) Der Zustandstyp muss vor der Aufzählung der Zustände bestimmt werden

(2) Dies führt zu einer Erhöhung der Anzahl von Systemklassen und -objekten.

(3) Die Unterstützung des „Open-Close-Prinzips“ erfordert keine Änderung des Quellcodes, der für die Statuskonvertierung verantwortlich ist, da sonst kein Wechsel in den neuen Status möglich ist Der Quellcode der entsprechenden Klasse muss ebenfalls geändert werden.

Das Zustandsmuster ist also geeignet für: Der Code enthält eine große Anzahl bedingter Anweisungen, die sich auf den Zustand des Objekts beziehen, und das Verhalten des Objekts hängt von seinem Zustand ab, und sein zugehöriges Verhalten kann entsprechend seinen Änderungen geändert werden Zustand. : Details zum Statusmodus: Verhaltenstyp des Java-Designmodus: Statusmodus

21, Verhaltens-Memo-Modus:

Der Memorandum-Modus bietet einen Mechanismus zur Wiederherstellung des Status zu einem bestimmten Zeitpunkt außerhalb des Objekts, um sicherzustellen, dass der Das Objekt kann in einem bestimmten historischen Zustand wiederhergestellt werden. Der Memo-Modus kapselt die gespeicherten Details im Memo, und kein anderes Objekt kann darauf zugreifen, außer dem Ersteller, der es erstellt hat, und erreicht dies, selbst wenn die gespeicherten Details geändert werden wird nicht beeinträchtigt. Der Memo-Modus ist jedoch Multi-State und Multi-Backup, wodurch mehr Speicher und Ressourcen verbraucht werden. Das UML-Strukturdiagramm des Memomusters lautet wie folgt:

Der Kern des Memorandum-Modus besteht darin, dass im Memorandum ein Teil oder alle Statusinformationen des Originalorgans zum Speichern dieser Statusinformationen verwendet werden Daher können andere Objekte als der Absender nicht auf das Memo zugreifen. Um also die Memo-Modus-Kapselung zu implementieren, müssen wir den Zugriff auf das Memo steuern:

(1) Für den Absender: Auf alle Informationen im Memo kann zugegriffen werden.

(2) Für den Verantwortlichen, Hausmeister: Auf die Daten im Memo kann nicht zugegriffen werden, er kann das Memo jedoch speichern und an andere Objekte weitergeben.

(3) Andere Objekte: Es kann nicht darauf zugegriffen werden und es kann nicht gespeichert werden. Es ist nur für den Empfang des von der verantwortlichen Person übergebenen Memos und die Wiederherstellung des Status des Originalgeräts verantwortlich.

Details zum Memento-Muster: Verhaltens-Java-Designmuster: Memento-Muster

22. Verhaltens-Iterator-Muster:

Das Iterator-Muster bietet eine Möglichkeit, auf einzelne Elemente in einer Sammlung zuzugreifen, ohne seine interne Darstellungsmethode offenzulegen. Übertragen Sie die Verantwortung für den Wechsel zwischen Elementen an Iteratoren statt an Sammlungsobjekte. Dies vereinfacht die Implementierung von Sammlungscontainern und ermöglicht es dem Sammlungscontainer, sich auf das zu konzentrieren, worauf er sich konzentrieren sollte, was eher dem Prinzip der Einzelverantwortung entspricht und die Notwendigkeit vermeidet Die abstrakte Schnittstellenschicht ist mit verschiedenen Traversierungsoperationen gefüllt. Das UML-Strukturdiagramm des Iteratormusters lautet wie folgt:

Details des Iteratormusters: Verhaltenstyp des Java-Entwurfsmusters: Iteratormuster

23. Verhaltenstyp – Interpretermuster:

Das Interpretermuster ist das Definition der Grammatik einer Sprache und Erstellen eines Dolmetschers zum Interpretieren von Sätzen in der Sprache. Lösen Sie durch den Aufbau des Dolmetschers eine bestimmte Art von Probleminstanz, die häufig auftritt.

                                                                                                                                                                                                 und wie man diese Sätze interpretiert. Im Interpretermodus können zusätzlich zur Verwendung grammatikalischer Regeln zur Definition einer Sprache auch abstrakte Syntaxbäume verwendet werden, um die Zusammensetzung einer Sprache intuitiver darzustellen und besser darzustellen. Jeder abstrakte Syntaxbaum entspricht einer Sprachinstanz. Der abstrakte Syntaxbaum beschreibt, wie ein komplexer Satz gebildet wird. Durch die Analyse des abstrakten Syntaxbaums können die terminalen und nichtterminalen Symbolklassen in der Sprache identifiziert werden. Da im Interpretermodus jedem Terminalausdruck und Nicht-Terminalausdruck eine bestimmte Instanz zugeordnet ist, ist die Skalierbarkeit des Systems besser.

Die UML des Interpretermusters lautet wie folgt:

Details des Interpretermusters: Verhaltenstyp des Java-Entwurfsmusters: Interpretermuster

Empfohlenes Lernen: „

Java-Lerntutorial

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in 23 gängige Java-Designmuster. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen