Patron Flyweight

Das Flyweight-Muster dient hauptsächlich dazu, die Anzahl der erzeugten Objekte zu verringern, wodurch der Speicherverbrauch gesenkt und die Leistung verbessert wird. Diese Art von Entwurfsmuster gehört zu den Strukturmustern; es bietet eine Möglichkeit, die Anzahl der Objekte zu reduzieren und dadurch die von der Anwendung benötigte Objektstruktur zu verbessern.

Das Flyweight-Muster versucht, vorhandene Objekte desselben Typs wiederzuverwenden; wenn kein passendes Objekt gefunden wird, wird ein neues Objekt erstellt. Wir demonstrieren dieses Muster, indem wir 20 Kreise an verschiedenen Positionen mit 5 Objekten zeichnen. Da nur 5 Farben verfügbar sind, wird das Farbattribut verwendet, um die vorhandenen zu prüfen.KreisObjekt.

summary

Absicht

Reduzieren Sie den Speicherverbrauch beim Erstellen einer großen Anzahl ähnlicher Objekte durch gemeinsame Nutzung von Objekten.

Gelöstes Hauptproblem

  • Vermeiden Sie Speicherüberlaufprobleme, die durch das Erstellen einer großen Anzahl von Objekten verursacht werden.
  • Verbessern Sie die Effizienz der Speichernutzung durch gemeinsame Nutzung von Objekten.

Anwendungsfall

  • Wenn es eine große Anzahl ähnlicher oder identischer Objekte im System gibt.
  • Die Kosten für das Erstellen und Zerstören von Objekten sind hoch.
  • Der Zustand von Objekten kann externalisiert werden, das heißt, ein Teil des Objektzustands kann unabhängig vom Objekt selbst existieren.

Implementierungsansatz

  • Definieren Sie die Flyweight-Schnittstelle: Erstellen Sie eine Flyweight-Schnittstelle, die den Zustand definiert, der gemeinsam genutzt werden kann.
  • Konkrete Flyweight-Klassen erstellen: Eine konkrete Klasse, die diese Schnittstelle implementiert und internen Zustand enthält.
  • Flyweight-Fabrik verwenden: Erstellen Sie eine Fabrikklasse, um die Erstellung und Wiederverwendung von Flyweight-Objekten zu verwalten.

Schlüsselcode

  • HashMap: Verwenden Sie eine Hash-Tabelle, um erstellte Flyweight-Objekte für den schnellen Abruf zu speichern.

Anwendungsbeispiel

  1. String-Objekte in Java.: Strings, die bereits im String-Konstantenpool vorhanden sind, werden wiederverwendet.
  2. Datenbankverbindungspool: Datenbankverbindungen werden wiederverwendet, um häufiges Erstellen und Zerstören von Verbindungen zu vermeiden.

Vorteile

  • Speicherverbrauch reduzieren: Durch das Teilen von Objekten wird die Anzahl der Objekte im Speicher verringert.
  • Effizienz verbessern: Reduziert die Objekterstellungszeit und verbessert die Systemeffizienz.

Nachteile

  • Erhöhung der Systemkomplexität: Interner Zustand und externer Zustand müssen getrennt werden, was die Komplexität von Entwurf und Implementierung erhöht.
  • Thread-Sicherheitsprobleme: Wenn der externe Zustand nicht ordnungsgemäß behandelt wird, kann dies zu Thread-Sicherheitsproblemen führen.

Verwendungshinweise

  • Erwägen Sie die Verwendung des Flyweight-Musters, wenn eine große Anzahl ähnlicher Objekte erstellt wird.
  • Stellen Sie sicher, dass der interne Zustand von Flyweight-Objekten geteilt wird, während der externe Zustand unabhängig vom Objekt ist.

Hinweise

  • Zustandstrennung: Internen Zustand klar vom externen Zustand unterscheiden, um Verwechslungen zu vermeiden.
  • Flyweight-Fabrik: Verwenden Sie eine Flyweight-Fabrik, um Objekterstellung und -wiederverwendung zu steuern und die Konsistenz und Integrität der Objekte sicherzustellen.

Struktur

Das Flyweight-Muster umfasst die folgenden Kernrollen:

  • Flyweight-Fabrik:

    • Verantwortlich für das Erstellen und Verwalten von Flyweight-Objekten, üblicherweise mit einem Pool (Cache) zum Speichern und Wiederverwenden erstellter Flyweight-Objekte.
  • Konkretes Flyweight:

    • Implementiert die abstrakte Flyweight-Schnittstelle und enthält internen Zustand und externen Zustand. Der interne Zustand kann geteilt werden, während der externe Zustand vom Client übergeben wird.
  • Abstraktes Flyweight:

    • Definiert die Schnittstelle für konkrete Flyweights und nicht geteilte Flyweights, üblicherweise einschließlich Methoden zum Setzen des externen Zustands.
  • Client:

    • Verwendet die Flyweight-Fabrik, um Flyweight-Objekte zu erhalten, und arbeitet mit Flyweight-Objekten, indem der externe Zustand gesetzt wird. Clients müssen sich üblicherweise nicht um die konkrete Implementierung von Flyweight-Objekten kümmern.

Implementierung

Wir werden eineShapeSchnittstelle und ImplementierungShapeEntitätsklassen der SchnittstelleCircle erstellenDer nächste Schritt ist, die Fabrikklasse zu definieren.ShapeFactory。

ShapeFactoryEs gibt eineCirclevonHashMap, wobei der Schlüsselname istCircleDie Farbe des Objekts. Immer wenn eine Anforderung eingeht, wird ein Kreis einer bestimmten Farbe erstellt.ShapeFactoryüberprüft ihreHashMapdas Kreisobjekt in der HashMap, wenn gefundenCircleObjekt, dann gib dieses Objekt zurück; andernfalls erstelle ein neues Objekt, das in der HashMap zur späteren Verwendung gespeichert wird, und gib es an den Client zurück.

FlyWeightPatternDemoKlassennutzungShapeFactoryzum Abrufen vonShapeObjekt. Es wirdShapeFactoryübergibt Informationen (red / green / blue/ black / white), um die Farbe des Objekts zu erhalten, das es benötigt.

享元模式的 UML 图

Schritt 1

eine Schnittstelle erstellen.

Shape.java

public interface Shape { void draw(); }

Schritt 2

Erstellen Sie konkrete Klassen, die die Schnittstelle implementieren.

Circle.java

public class Circle implements Shape { private String color; private int x; private int y; private int radius; public Circle(String color){ this.color = color; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setRadius(int radius) { this.radius = radius; } @Override public void draw() { System.out.println("Circle: Draw() [Color : " + color +", x : " + x +", y :" + y +", radius :" + radius); } }

Schritt 3

Erstellen Sie eine Fabrik, die Objekte von Entitätsklassen basierend auf den angegebenen Informationen generiert.

ShapeFactory.java

import java.util.HashMap; public class ShapeFactory { private static final HashMap<String, Shape> circleMap = new HashMap<>(); public static Shape getCircle(String color) { Circle circle = (Circle)circleMap.get(color); if(circle == null) { circle = new Circle(color); circleMap.put(color, circle); System.out.println("Kreis mit Farbe wird erstellt: " + color); } return circle; } }

Schritt 4

Verwenden Sie diese Fabrik, um Entitätsklassenobjekte durch Übergeben von Farbinformationen zu erhalten.

FlyweightPatternDemo.java

public class FlyweightPatternDemo { private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" }; public static void main(String[] args) { for(int i=0; i < 20; ++i) { Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); circle.setY(getRandomY()); circle.setRadius(100); circle.draw(); } } private static String getRandomColor() { return colors[(int)(Math.random()*colors.length)]; } private static int getRandomX() { return (int)(Math.random()*100 ); } private static int getRandomY() { return (int)(Math.random()*100); } }

Schritt 5

Führen Sie das Programm aus, Ausgabeergebnis:

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100
Weitere Erweiterungen