


Maîtriser le modèle de conception de stratégie : un guide pour les développeurs
Als Softwareentwickler stehen wir ständig vor der Aufgabe, wartbare, flexible und erweiterbare Systeme zu schaffen. Design Patterns sind in diesem Zusammenhang leistungsstarke Werkzeuge, die uns helfen, wiederkehrende Probleme strukturiert und wiederverwendbar zu lösen. Ein solches Entwurfsmuster ist das Strategiemuster, das Teil der Familie der Verhaltensmuster ist.
Das Strategiemuster ermöglicht es Ihnen, eine Familie von Algorithmen zu definieren, jeden einzelnen zu kapseln und sie austauschbar zu machen. Das bedeutet, dass der Client zur Laufzeit den passenden Algorithmus oder die passende Strategie wählen kann, ohne die Kernfunktionalität des Systems zu verändern.
In diesem Blog werde ich mich eingehend mit dem Strategiemuster, seinen Schlüsselkonzepten und Komponenten, einem Beispiel aus der realen Welt und wann und warum Sie es verwenden sollten, befassen. Wir werden auch untersuchen, wie das Strategiemuster mit Abstraktion, Aufzählungen und sogar dem Fabrikmuster funktioniert, um das Design robuster und flexibler zu machen.
Was ist das Strategieentwurfsmuster?
Das Strategiemuster ist ein Verhaltensentwurfsmuster, das es ermöglicht, das Verhalten eines Algorithmus zur Laufzeit auszuwählen. Anstelle eines einzelnen, monolithischen Algorithmus ermöglicht das Strategiemuster die Austauschbarkeit des Verhaltens (oder der Strategie), wodurch das System flexibler und einfacher zu warten ist.
Kernidee:
- Definieren Sie eine Familie von Algorithmen (Strategien).
- Kapseln Sie jeden Algorithmus in einer separaten Klasse.
- Machen Sie die Algorithmen austauschbar.
- Lassen Sie den Client auswählen, welcher Algorithmus zur Laufzeit verwendet werden soll.
Wann und warum sollten Sie das Strategiemuster verwenden?
Anwendungsfälle:
Das Strategiemuster ist besonders nützlich, wenn:
- Sie haben eine Familie von Algorithmen und der Client muss einen zur Ausführung auswählen.
- Sie müssen verschiedene Verhaltensweisen dynamisch auswählen (z. B. Sortierung, Preisgestaltung, Zahlungsabwicklung).
- Das Verhalten ist unabhängig vom Klienten, variiert jedoch je nach Kontext.
- Sie möchten große bedingte Anweisungen (wie if oder switch) vermeiden, die entscheiden, welches Verhalten ausgeführt werden soll.
Warum es verwenden?
Trennung von Belangen: Das Strategiemuster trennt die Belange des Algorithmus vom Rest des Systems. Der Client-Code weiß nicht, wie der Algorithmus intern funktioniert, wodurch er modularer wird.
Erweiterbarkeit: Neue Algorithmen können ohne Änderung des vorhandenen Codes hinzugefügt werden, indem einfach neue Strategieklassen hinzugefügt werden.
Wartbarkeit: Es reduziert die Komplexität des Codes, indem es unterschiedliche Verhaltensweisen an einzelne Strategieklassen delegiert, was die Wartung erleichtert.
Wann nicht verwenden?
Einfache Algorithmen: Wenn der Algorithmus, mit dem Sie arbeiten, unkompliziert ist und sich nicht ändert, kann die Verwendung eines Strategiemusters übertrieben sein.
Zu viele Strategien: Wenn Sie über eine große Anzahl von Strategien verfügen, kann dies zu einer Explosion von Klassen führen, was die Lesbarkeit beeinträchtigen und die Komplexität erhöhen kann.
Seltene Änderungen: Wenn sich der Algorithmus nicht oft ändert, kann die Einführung des Strategiemusters zu unnötiger Komplexität führen.
Schlüsselkonzepte und Komponenten des Strategiemusters
Das Strategiemuster besteht aus den folgenden Schlüsselkomponenten:
-
Kontext:
- Dies ist die Klasse, die mit einem Strategieobjekt interagiert. Es enthält typischerweise einen Verweis auf eine Strategie und delegiert das tatsächliche Verhalten an diese Strategie.
-
Strategie:
- Dies ist eine Schnittstelle (oder abstrakte Klasse), die eine Methode zum Ausführen des Algorithmus deklariert. Konkrete Strategien implementieren diese Schnittstelle, um unterschiedliche Verhaltensweisen bereitzustellen.
-
Konkrete Strategie:
- Dies sind die Klassen, die die Strategy-Schnittstelle implementieren und bestimmte Algorithmen oder Verhaltensweisen definieren.
Beispiel aus der Praxis: Zahlungsabwicklungssystem
Betrachten wir ein Zahlungsabwicklungssystem, das es Benutzern ermöglicht, mit verschiedenen Methoden wie Kreditkarte, PayPal und Kryptowährung zu bezahlen. Das Verhalten bei der Verarbeitung von Zahlungen unterscheidet sich für jede Methode, aber der Kontext (in diesem Fall der Einkaufswagen) muss in der Lage sein, Zahlungen zu verarbeiten, ohne sich um die Besonderheiten der einzelnen Zahlungsmethoden kümmern zu müssen.
Schritt 1: Definieren Sie die PaymentMethod-Enumeration
Wir beginnen mit der Verwendung einer Enumeration, um verschiedene Zahlungsmethoden zu definieren. Dadurch wird die Auswahl der Zahlungsmethode typsicher und einfacher zu verwalten.
public enum PaymentMethod { CREDIT_CARD, PAYPAL, CRYPTOCURRENCY; }
Schritt 2: Erstellen Sie die PaymentInformation-Klasse
Diese Klasse kapselt die Details, die zur Verarbeitung einer Zahlung erforderlich sind. Es enthält die Zahlungsmethode und die Zahlungsdetails (wie Kartennummer, E-Mail oder Kryptowährungsadresse).
public class PaymentInformation { private PaymentMethod paymentMethod; private String paymentDetails; public PaymentInformation(PaymentMethod paymentMethod, String paymentDetails) { this.paymentMethod = paymentMethod; this.paymentDetails = paymentDetails; } public PaymentMethod getPaymentMethod() { return paymentMethod; } public String getPaymentDetails() { return paymentDetails; } }
Schritt 3: Definieren Sie die PaymentStrategy-Schnittstelle
Dies wird die Basisschnittstelle für alle Zahlungsstrategien sein. Es definiert die gemeinsame Methode pay(), die alle konkreten Strategien implementieren.
public abstract class PaymentStrategy { protected PaymentInformation paymentInformation; public PaymentStrategy(PaymentInformation paymentInformation) { this.paymentInformation = paymentInformation; } public abstract void pay(double amount); protected boolean validatePaymentDetails() { return paymentInformation != null && paymentInformation.getPaymentDetails() != null && !paymentInformation.getPaymentDetails().isEmpty(); } }
Step 4: Implement Concrete Strategies
Here, we implement the concrete strategies for CreditCardPayment, PayPalPayment, and CryptoPayment. Each of these classes implements the pay() method according to the payment type.
Credit Card Payment Strategy
public class CreditCardPayment extends PaymentStrategy { public CreditCardPayment(PaymentInformation paymentInformation) { super(paymentInformation); } @Override public void pay(double amount) { if (validatePaymentDetails()) { System.out.println("Paid " + amount + " using Credit Card: " + paymentInformation.getPaymentDetails()); } else { System.out.println("Invalid Credit Card details."); } } }
PayPal Payment Strategy
public class PayPalPayment extends PaymentStrategy { public PayPalPayment(PaymentInformation paymentInformation) { super(paymentInformation); } @Override public void pay(double amount) { if (validatePaymentDetails()) { System.out.println("Paid " + amount + " using PayPal: " + paymentInformation.getPaymentDetails()); } else { System.out.println("Invalid PayPal details."); } } }
Cryptocurrency Payment Strategy
public class CryptoPayment extends PaymentStrategy { public CryptoPayment(PaymentInformation paymentInformation) { super(paymentInformation); } @Override public void pay(double amount) { if (validatePaymentDetails()) { System.out.println("Paid " + amount + " using Cryptocurrency to address: " + paymentInformation.getPaymentDetails()); } else { System.out.println("Invalid cryptocurrency address."); } } }
Step 5: Factory to Select the Strategy
We will use the Factory Pattern to instantiate the appropriate payment strategy based on the payment method. This makes the system more flexible and allows the client to select a payment method at runtime.
public class PaymentStrategyFactory { public static PaymentStrategy createPaymentStrategy(PaymentInformation paymentInformation) { switch (paymentInformation.getPaymentMethod()) { case CREDIT_CARD: return new CreditCardPayment(paymentInformation); case PAYPAL: return new PayPalPayment(paymentInformation); case CRYPTOCURRENCY: return new CryptoPayment(paymentInformation); default: throw new IllegalArgumentException("Unsupported payment method: " + paymentInformation.getPaymentMethod()); } } }
Step 6: Client Code (ShoppingCart)
The ShoppingCart class is the context where the payment strategy is used. It delegates the payment responsibility to the strategy selected by the factory.
public class ShoppingCart { private PaymentStrategy paymentStrategy; public ShoppingCart(PaymentInformation paymentInformation) { this.paymentStrategy = PaymentStrategyFactory.createPaymentStrategy(paymentInformation); } public void checkout(double amount) { paymentStrategy.pay(amount); } public void setPaymentInformation(PaymentInformation paymentInformation) { this.paymentStrategy = PaymentStrategyFactory.createPaymentStrategy(paymentInformation); } }
Step 7: Running the Example
public class Main { public static void main(String[] args) { PaymentInformation cardInfo = new PaymentInformation(PaymentMethod.CREDIT_CARD, "1234-5678-9876"); ShoppingCart cart = new ShoppingCart(cardInfo); cart.checkout(250.0); PaymentInformation paypalInfo = new PaymentInformation(PaymentMethod.PAYPAL, "john.doe@example.com"); cart.setPaymentInformation(paypalInfo); cart.checkout(150.0); PaymentInformation cryptoInfo = new PaymentInformation(PaymentMethod.CRYPTOCURRENCY, "1A2B3C4D5E6F"); cart.setPaymentInformation(cryptoInfo); cart.checkout(500.0); } }
Output:
Paid 250.0 using Credit Card: 1234-5678-9876 Paid 150.0 using PayPal: john.doe@example.com Paid 500.0 using Cryptocurrency to address: 1A2B3C4D5E6F
Benefits of the Strategy Pattern
- Flexibility: Strategies can be easily swapped at runtime, allowing dynamic
behavior changes without modifying the core logic.
- Erweiterbarkeit: Das Hinzufügen neuer Strategien erfordert keine Änderung des vorhandenen Codes; Sie erstellen einfach neue Strategieklassen.
- Bedenkenstrennung: Die Strategie kapselt den Algorithmus, sodass die Kontextklasse (z. B. ShoppingCart) nicht weiß, wie die Zahlung verarbeitet wird.
- Wartbarkeit: Code ist sauberer und wartbarer, da die Logik für jede Strategie in einer eigenen Klasse isoliert ist.
Nachteile des Strategiemusters
- Komplexität: Durch die Einführung mehrerer Strategien erhöht sich die Anzahl der Klassen im System, was die Navigation erschweren kann, insbesondere bei einfachen Anwendungsfällen.
- Overhead: In einigen Fällen, wenn die Anzahl der Strategien gering ist, kann die Verwendung dieses Musters zu unnötiger Abstraktion und Overhead führen.
- Abhängigkeitsmanagement: Die Verwaltung von Abhängigkeiten zwischen Strategien und deren Initialisierung kann zusätzlichen Aufwand erfordern, insbesondere wenn Strategien von externen Ressourcen abhängen.
Fazit
Das Strategiemuster ist ein wesentliches Entwurfsmuster, um Flexibilität und Modularität in Ihrem System zu erreichen. Es bietet eine elegante Möglichkeit, Algorithmen zu kapseln und ermöglicht Laufzeitflexibilität, ohne vorhandenen Code zu ändern. Egal, ob Sie ein Zahlungsverarbeitungssystem, eine Sortieralgorithmus-Bibliothek oder sogar eine Gaming-KI-Engine erstellen, das Strategiemuster kann dazu beitragen, dass Ihr Code wartbarer, erweiterbarer und einfacher zu ändern ist, wenn sich die Anforderungen ändern.
Durch die Nutzung von Abstraktion, Aufzählungen und dem Factory-Muster können Sie noch robustere Systeme erstellen, die sowohl typsicher als auch flexibel sind.
Weiterführende Literatur
- Design Patterns: Elemente wiederverwendbarer objektorientierter Software von Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides – das bahnbrechende Buch, das viele Designmuster, einschließlich des Strategiemusters, vorstellte.
- Head First Design Patterns von Eric Freeman, Elisabeth Robson – eine zugängliche Einführung in Design Patterns mit praktischen Beispielen.
- Refactoring: Improving the Design of Existing Code von Martin Fowler – untersucht den Wert von Entwurfsmustern beim Refactoring von Code für eine bessere Wartbarkeit.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Dépannage et solutions au logiciel de sécurité de l'entreprise qui fait que certaines applications ne fonctionnent pas correctement. De nombreuses entreprises déploieront des logiciels de sécurité afin d'assurer la sécurité des réseaux internes. ...

Le traitement de la cartographie des champs dans l'amarrage du système rencontre souvent un problème difficile lors de l'exécution d'amarrage du système: comment cartographier efficacement les champs d'interface du système a ...

Lorsque vous utilisez MyBatis-Plus ou d'autres cadres ORM pour les opérations de base de données, il est souvent nécessaire de construire des conditions de requête en fonction du nom d'attribut de la classe d'entité. Si vous manuellement à chaque fois ...

Solutions pour convertir les noms en nombres pour implémenter le tri dans de nombreux scénarios d'applications, les utilisateurs peuvent avoir besoin de trier en groupe, en particulier en un ...

Commencez le printemps à l'aide de la version IntelliJideaultimate ...

Conversion des objets et des tableaux Java: Discussion approfondie des risques et des méthodes correctes de la conversion de type de distribution De nombreux débutants Java rencontreront la conversion d'un objet en un tableau ...

Explication détaillée de la conception des tables SKU et SPU sur les plates-formes de commerce électronique Cet article discutera des problèmes de conception de la base de données de SKU et SPU dans les plateformes de commerce électronique, en particulier comment gérer les ventes définies par l'utilisateur ...

Lorsque vous utilisez TkMyBatis pour les requêtes de base de données, comment obtenir gracieusement les noms de variables de classe d'entité pour créer des conditions de requête est un problème courant. Cet article épinglera ...
