Bei der Anwendungsentwicklung kann die Verwaltung der Objekterstellung komplex sein, insbesondere wenn es sich um Instanzen handelt, die nahezu identisch sind, sich aber in bestimmten Details unterscheiden. Das Prototype Design Pattern bietet eine Lösung, indem es uns ermöglicht, neue Objekte durch Kopieren oder „Klonen“ vorhandener Objekte zu erstellen. Dieses Muster ist besonders nützlich, wenn die Erstellung von Objekten teuer ist oder eine umfangreiche Initialisierung erfordert.
In diesem Artikel untersuchen wir anhand eines praktischen E-Commerce-Anwendungsfalls, wie Sie das Prototype Design Pattern in einer Spring Boot-Anwendung implementieren: Erstellen und Beibehalten von Produktvarianten. Anhand dieses Beispiels lernen Sie nicht nur die Grundlagen des Prototypmusters kennen, sondern auch, wie es die Objekterstellung in realen Anwendungen optimieren kann.
Das Prototypmuster ist ein kreatives Entwurfsmuster, mit dem Sie neue Instanzen erstellen können, indem Sie ein vorhandenes Objekt, den sogenannten Prototyp, klonen. Dieser Ansatz ist besonders nützlich, wenn Sie ein Basisobjekt mit verschiedenen Eigenschaften haben und die Erstellung jeder Variante von Grund auf überflüssig und ineffizient wäre.
In Java wird dieses Muster häufig mithilfe der Cloneable-Schnittstelle oder durch die Definition einer benutzerdefinierten Klonmethode implementiert. Die Hauptidee besteht darin, eine „Blaupause“ bereitzustellen, die mit Änderungen repliziert werden kann und dabei das Originalobjekt intakt hält.
Reduziert die Initialisierungszeit: Anstatt Objekte von Grund auf neu zu erstellen, klonen und ändern Sie vorhandene Instanzen und sparen so Initialisierungszeit.
Kapselt die Objekterstellungslogik: Sie definieren, wie Objekte innerhalb des Objekts selbst geklont werden, wobei Instanziierungsdetails verborgen bleiben.
Verbessert die Leistung: Bei Anwendungen, die häufig ähnliche Objekte erstellen, wie z. B. Produktvarianten, kann das Prototypmuster die Leistung verbessern.
Stellen Sie sich eine E-Commerce-Plattform vor, bei der ein Basisprodukt verschiedene Konfigurationen oder „Varianten“ hat – zum Beispiel ein Smartphone mit unterschiedlichen Farben, Speicheroptionen und Garantiebedingungen. Anstatt jede Variante von Grund auf neu zu erstellen, können wir ein Basisprodukt klonen und dann bestimmte Felder nach Bedarf anpassen. Auf diese Weise bleiben die gemeinsamen Attribute konsistent und wir ändern nur die variantenspezifischen Details.
In unserem Beispiel erstellen wir einen einfachen Spring Boot-Dienst, um Produktvarianten mithilfe des Prototypmusters zu erstellen und beizubehalten.
Beginnen Sie mit der Definition einer Produktklasse mit den notwendigen Feldern für ein Produkt, wie ID, Name, Farbe, Modell, Lagerung, Garantie und Preis. Wir werden auch eine cloneProduct-Methode zum Erstellen einer Kopie eines Produkts hinzufügen.
public interface ProductPrototype extends Cloneable { ProductPrototype cloneProduct(); }
@Entity @Table(name = "products") @Data public class Product implements ProductPrototype { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "product_id") private Long productId; @Column(name = "name") private String name; @Column(name = "model") private String model; @Column(name = "color") private String color; @Column(name = "storage") private int storage; @Column(name = "warranty") private int warranty; @Column(name = "price") private double price; @Override public ProductPrototype cloneProduct() { try { Product product = (Product) super.clone(); product.setId(null); // database will assign new Id for each cloned instance return product; } catch (CloneNotSupportedException e) { return null; } } }
In diesem Setup:
cloneProduct: Diese Methode erstellt einen Klon des Product-Objekts und setzt die ID auf Null, um sicherzustellen, dass die Datenbank jeder geklonten Instanz eine neue ID zuweist.
Als nächstes erstellen Sie einen ProductService mit einer Methode zum Speichern der Variante. Diese Methode klont ein Basisprodukt, wendet die variantenspezifischen Attribute an und speichert es dann als neues Produkt.
public interface ProductService { // For saving the base product Product saveBaseProduct(Product product); // For saving the variants Product saveVariant(Long baseProductId, VariantRequest variant); }
@Log4j2 @Service public class ProductServiceImpl implements ProductService { private final ProductRepository productRepository; public ProductServiceImpl(ProductRepository productRepository) { this.productRepository = productRepository; } /** * Saving Base product, Going to use this object for cloning * * @param product the input * @return Product Object */ @Override public Product saveBaseProduct(Product product) { log.debug("Save base product with the detail {}", product); return productRepository.save(product); } /** * Fetching the base product and cloning it to add the variant informations * * @param baseProductId baseProductId * @param variant The input request * @return Product */ @Override public Product saveVariant(Long baseProductId, VariantRequest variant) { log.debug("Save variant for the base product {}", baseProductId); Product baseProduct = productRepository.findByProductId(baseProductId) .orElseThrow(() -> new NoSuchElementException("Base product not found!")); // Cloning the baseProduct and adding the variant details Product variantDetail = (Product) baseProduct.cloneProduct(); variantDetail.setColor(variant.color()); variantDetail.setModel(variant.model()); variantDetail.setWarranty(variant.warranty()); variantDetail.setPrice(variant.price()); variantDetail.setStorage(variant.storage()); // Save the variant details return productRepository.save(variantDetail); } }
In diesem Service:
saveVariant: Diese Methode ruft das Basisprodukt anhand der ID ab, klont es, wendet die Details der Variante an und speichert es als neuen Eintrag in der Datenbank.
Erstellen Sie einen einfachen REST-Controller, um die Variantenerstellungs-API verfügbar zu machen.
@RestController @RequestMapping("/api/v1/products") @Log4j2 public class ProductController { private final ProductService productService; public ProductController(ProductService productService) { this.productService = productService; } @PostMapping public ResponseEntity<Product> saveBaseProduct(@RequestBody Product product) { log.debug("Rest request to save the base product {}", product); return ResponseEntity.ok(productService.saveBaseProduct(product)); } @PostMapping("/{baseProductId}/variants") public ResponseEntity<Product> saveVariants(@PathVariable Long baseProductId, @RequestBody VariantRequest variantRequest) { log.debug("Rest request to create the variant for the base product"); return ResponseEntity.ok(productService.saveVariant(baseProductId, variantRequest)); } }
Hier:
saveVariant: Dieser Endpunkt verarbeitet HTTP-POST-Anfragen, um eine Variante für ein bestimmtes Produkt zu erstellen. Es delegiert die Erstellungslogik an ProductService.
Mit dieser Implementierung sehen wir mehrere klare Vorteile:
Wiederverwendbarkeit des Codes: Durch die Kapselung der Klonlogik in der Produktklasse vermeiden wir Codeduplizierung in unseren Service- und Controller-Schichten.
Vereinfachte Wartung: Das Prototypmuster zentralisiert die Klonlogik und erleichtert so die Verwaltung von Änderungen an der Objektstruktur.
Effiziente Variantenerstellung: Jede neue Variante ist ein Klon des Basisprodukts, wodurch redundante Dateneingaben reduziert und die Konsistenz über gemeinsame Attribute hinweg sichergestellt wird.
./gradlew build ./gradlew bootRun
Basisprodukt speichern
curl --location 'http://localhost:8080/api/v1/products' \ --header 'Content-Type: application/json' \ --data '{ "productId": 101, "name": "Apple Iphone 16", "model": "Iphone 16", "color": "black", "storage": 128, "warranty": 1, "price": 12.5 }'
Varianten speichern
curl --location 'http://localhost:8080/api/v1/products/101/variants' \ --header 'Content-Type: application/json' \ --data '{ "model": "Iphone 16", "color": "dark night", "storage": 256, "warranty": 1, "price": 14.5 }'
Ergebnis (Neue Variante blieb ohne Probleme bestehen)
Die vollständige Implementierung des Prototype Design Pattern für Produktvarianten finden Sie im folgenden GitHub-Repository:
GitHub-Repository-Link
Bleiben Sie in Verbindung und folgen Sie mir für weitere Artikel, Tutorials und Einblicke in Softwareentwicklung, Designmuster und Spring Boot:
Folgen Sie mir auf LinkedIn
Das Prototype Design Pattern ist ein leistungsstarkes Werkzeug für Fälle, in denen Objektduplizierungen häufig vorkommen, wie es bei Produktvarianten in E-Commerce-Anwendungen der Fall ist. Durch die Implementierung dieses Musters in einer Spring Boot-Anwendung verbessern wir sowohl die Effizienz der Objekterstellung als auch die Wartbarkeit unseres Codes. Dieser Ansatz ist besonders nützlich in Szenarien, die die Erstellung ähnlicher Objekte mit kleinen Variationen erfordern, was ihn zu einer wertvollen Technik für die Anwendungsentwicklung in der Praxis macht.
Das obige ist der detaillierte Inhalt vonImplementierung des Prototyp-Entwurfsmusters in Spring Boot. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!