Prototyp-Muster

Das Prototyp-Muster wird verwendet, um Objekte zu duplizieren, während die Leistung sichergestellt wird. Diese Art von Entwurfsmuster gehört zu den Erzeugungsmustern und bietet eine der besten Möglichkeiten, Objekte zu erstellen.

Dieses Muster implementiert eine Prototyp-Schnittstelle, die verwendet wird, um einen Klon des aktuellen Objekts zu erstellen. Dieses Muster wird verwendet, wenn das direkte Erstellen eines Objekts relativ aufwendig ist. Beispielsweise muss ein Objekt nach einer teuren Datenbankoperation erstellt werden. Wir können das Objekt zwischenspeichern, bei der nächsten Anfrage seinen Klon zurückgeben und die Datenbank bei Bedarf aktualisieren, wodurch Datenbankaufrufe reduziert werden.

summary

Prototyp-Muster

Absicht: Verwenden Sie Prototyp-Instanzen, um die Arten von Objekten anzugeben, die erstellt werden sollen, und erstellen Sie neue Objekte durch Kopieren dieser Prototypen.

Hauptsächlich gelöst: Prototypen zur Laufzeit dynamisch erstellen und löschen.

Wann verwenden

  • Das System sollte unabhängig von der Erzeugung, Zusammensetzung und Darstellung von Produkten sein.
  • Die zu instanziierende Klasse muss zur Laufzeit angegeben werden, beispielsweise durch dynamisches Laden.
  • Vermeiden Sie die Erstellung einer Factory-Klassenhierarchie parallel zur Produktklassenhierarchie.
  • Instanzen einer Klasse können nur wenige verschiedene Zustandskombinationen haben; das Klonen eines Prototyps ist bequemer als die manuelle Instanziierung.

Lösung

Schnelles Erzeugen einer Instanz, die mit dem Prototypobjekt identisch ist, durch Verwendung eines vorhandenen Prototypobjekts.

Schlüsselcode

  • Implementieren Sie die Clone-Operation:
    • In Java implementierenCloneableInterface, überschreibenclone()Methode.
    • In .NET verwendenObjectKlasseMemberwiseClone()Die Methode implementiert flache Kopie oder tiefe Kopie mittels Serialisierung.
  • Isolieren Sie die Kopplung zwischen Benutzern von Klassenobjekten und konkreten Typen, wobei "volatile Klassen" stabile Schnittstellen haben müssen.

Anwendungsbeispiel

  • Zellteilung
  • In JavaObject.clone()Methoden

Vorteile

  • Leistungsverbesserung
  • Konstruktorbeschränkungen vermeiden

Nachteile

  • Das Ausstatten einer Klasse mit Clone-Methoden erfordert eine umfassende Berücksichtigung der Funktionalität der Klasse, was bei bestehenden Klassen schwierig sein kann, insbesondere beim Umgang mit indirekten Objekten, die keine Serialisierung unterstützen, oder Verweisen, die zirkuläre Strukturen enthalten.
  • Muss implementiert werdenCloneableSchnittstelle.

Anwendungsfall

  • Ressourcenoptimierung
  • Wenn die Klasseninitialisierung eine große Menge an Ressourcen verbraucht (z. B. Daten, Hardware-Ressourcen).
  • Szenarien mit hohen Leistungs- und Sicherheitsanforderungen
  • DurchnewWenn das Erstellen eines Objekts komplexe Datenvorbereitung oder Zugriffsberechtigungen erfordert.
  • Ein Objekt erfordert mehrere Modifizierer
  • Wenn ein Objekt anderen Objekten zum Zugriff bereitgestellt werden muss und von verschiedenen Aufrufern geändert werden kann.
  • Es wird häufig zusammen mit dem Factory-Method-Muster verwendet, durchclonedas Erstellen von Objekten, die dann von der Factory-Methode an Aufrufer übergeben werden.

Hinweise

Im Gegensatz zum direkten Instanziieren einer Klasse, um ein neues Objekt zu erstellen, erzeugt das Prototype-Muster neue Objekte durch Kopieren vorhandener Objekte. Eine flache Kopie wird durch Implementieren vonCloneablewährend eine tiefe Kopie durch Implementieren vonSerializableLesen von binären Streams.

Struktur

Das Prototype-Muster umfasst die folgenden Hauptrollen:

  • Prototype-Schnittstelle: Definiert eine Schnittstelle zum Klonen von sich selbst, üblicherweise einschließlich einerclone()Methode.

  • Konkreter Prototyp: Eine konkrete Klasse, die die Prototype-Schnittstelle implementiert und für die eigentliche Klonoperation verantwortlich ist. Diese Klasse muss dieclone()Methode, die üblicherweise eine flache Kopie oder eine tiefe Kopie verwendet, um sich selbst zu kopieren.

  • Client: Verwenden Sie Prototypinstanzen, um neue Objekte zu erstellen. Der Client ruft dieclone()Methode des Prototypobjekts auf, um neue Objekte zu erstellen, anstatt direkt Konstruktoren zu verwenden.

Implementierung

Wir werden eine abstrakte KlasseShapeerstellen und konkrete Klassen, dieShapeerweitern. Der nächste Schritt ist die Definition der KlasseShapeCache, diese Klasse speichert Shape-Objekte in einerHashtableund gibt deren Klone auf Anfrage zurück.

PrototypePatternDemoKlasse verwendet dieShapeCache-Klasse, um einShape-Objekt zu erhalten.

原型模式的 UML 图

Schritt 1

Erstelle eine abstrakte Klasse, dieCloneableimplements das Interface.

Shape.java

public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }

Schritt 2

Erstellen Sie Entitätsklassen, die die obige abstrakte Klasse erweitern.

Rectangle.java

public class Rectangle extends Shape { public Rectangle(){ type = "Rectangle"; } @Override public void draw() { System.out.println("Innerhalb der Methode Rectangle::draw()."); } }

Square.java

public class Square extends Shape { public Square(){ type = "Square"; } @Override public void draw() { System.out.println("Innerhalb der Methode Square::draw()."); } }

Circle.java

public class Circle extends Shape { public Circle(){ type = "Circle"; } @Override public void draw() { System.out.println("Innerhalb der Methode Circle::draw()."); } }

Schritt 3

Erstellen Sie eine Klasse, die Entitätsklassen aus einer Datenbank abruft und sie in einerHashtableIn.

ShapeCache.java

import java.util.Hashtable; public class ShapeCache { private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } //Führen Sie eine Datenbankabfrage für jede Form aus und erstellen Sie diese Form // shapeMap.put(shapeKey, shape); //Zum Beispiel möchten wir drei Formen hinzufügen public static void loadCache() { Circle circle = new Circle(); circle.setId("1"); shapeMap.put(circle.getId(),circle); Square square = new Square(); square.setId("2"); shapeMap.put(square.getId(),square); Rectangle rectangle = new Rectangle(); rectangle.setId("3"); shapeMap.put(rectangle.getId(),rectangle); } }

Schritt 4

PrototypePatternDemoVerwendungShapeCacheKlasse zum Abrufen des inHashtablegespeicherten Prototyps, der Kopie der darin enthaltenen Form.

PrototypePatternDemo.java

public class PrototypePatternDemo { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape = (Shape) ShapeCache.getShape("1"); System.out.println("Shape : " + clonedShape.getType()); Shape clonedShape2 = (Shape) ShapeCache.getShape("2"); System.out.println("Shape : " + clonedShape2.getType()); Shape clonedShape3 = (Shape) ShapeCache.getShape("3"); System.out.println("Shape : " + clonedShape3.getType()); } }

Schritt 5

Führen Sie das Programm aus, Ausgabeergebnis:

Shape : Circle
Shape : Square
Shape : Rectangle
Weitere Erweiterungen