Strategy-Muster
Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 55 von 70.
Das Strategy-Muster ist ein Verhaltensmuster, mit dem du eine Familie von Algorithmen definieren, jeden einzelnen in seiner eigenen Klasse kapseln und sie zur Laufzeit austauschbar machen kannst. Anstatt das Verhalten fest zu codieren, injizierst du die gewünschte Strategie in ein Objekt.
Das Muster besteht aus drei Teilen: einer Strategieschnittstelle, die den Algorithmusvertrag definiert, konkreten Strategiestrategien, die unterschiedliche Verhaltensweisen implementieren, und einer Kontextklasse, die eine Strategie verwendet:
public interface IPaymentStrategy
{
void Pay(decimal amount);
}
public class CreditCardPayment : IPaymentStrategy
{
public void Pay(decimal amount) =>
Console.WriteLine($"Paid {amount} via Credit Card");
}
public class PayPalPayment : IPaymentStrategy
{
public void Pay(decimal amount) =>
Console.WriteLine($"Paid {amount} via PayPal");
}
public class ShoppingCart
{
private IPaymentStrategy _paymentStrategy;
public void SetPaymentMethod(IPaymentStrategy strategy)
{
_paymentStrategy = strategy;
}
public void Checkout(decimal total)
{
_paymentStrategy.Pay(total);
}
}Der Kontext (ShoppingCart) weiß nicht, welche Zahlungsmethode er verwendet – er ruft einfach Pay() für die bereitgestellte Strategie auf:
var cart = new ShoppingCart();
cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m); // Bezahlt 99.99 via Kreditkarte
cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m); // Bezahlt 49.99 via PayPalDas Strategy-Muster beseitigt komplexe bedingte Logik. Das Hinzufügen einer neuen Zahlungsmethode bedeutet, eine neue Klasse zu erstellen, die IPaymentStrategy implementiert – keine Änderungen in ShoppingCart erforderlich. Dadurch ist dein Code für Erweiterungen offen, aber für Änderungen geschlossen.
Aufgabe
EinfachErstellen wir einen Versandkostenrechner mithilfe des Strategy-Musters. Verschiedene Versandarten haben unterschiedliche Preisalgorithmen, und dein System sollte es ermöglichen, zur Laufzeit zwischen ihnen zu wechseln, ohne die zentrale Bestellverarbeitungslogik zu ändern.
Du organisierst deinen Code über drei Dateien:
ShippingStrategy.cs: Definiere im NamespaceShippingeinIShippingStrategy-Interface mit einer MethodeCalculateCost(double weight), die einendoublezurückgibt. Erstelle anschließend drei konkrete Strategienklassen:StandardShipping– berechnet die Kosten alsweight * 1.5ExpressShipping– berechnet die Kosten alsweight * 3.0 + 5.0(einschließlich einer pauschalen Expressgebühr)OvernightShipping– berechnet die Kosten alsweight * 5.0 + 10.0(Premium-Service mit höherer Grundgebühr)
OrderProcessor.cs: Erstelle im selben Namespace eineOrderProcessor-Klasse. Dies ist deine Kontextklasse, die eine Versandstrategie verwendet. Sie sollte Folgendes enthalten:- Ein privates Feld, das die aktuelle
IShippingStrategyenthält - Eine
SetShippingMethod(IShippingStrategy strategy)-Methode zum Ändern der Versandstrategie - Eine
ProcessOrder(double weight)-Methode, die die aktuelle Strategie verwendet, um die Versandkosten zu berechnen und zurückzugeben
- Ein privates Feld, das die aktuelle
Program.cs: Führe alles zusammen, indem du einenOrderProcessorerstellst und demonstrierst, wie du Versandstrategien zur Laufzeit austauschen kannst. Derselbe Prozessor kann Kosten mit unterschiedlichen Algorithmen berechnen, indem einfach seine Strategie geändert wird.
Du erhältst zwei Eingaben:
- Den Typ der Versandart:
standard,expressoderovernight - Das Paketgewicht als Dezimalzahl (z. B.
4.5)
Erstelle einen OrderProcessor, lege die passende Versandstrategie basierend auf dem Eingabetyp fest, verarbeite anschließend die Bestellung und gib die berechneten Kosten aus.
Wenn die Eingaben beispielsweise express und 4.5 lauten, sollte die Ausgabe wie folgt aussehen:
18.5Dies veranschaulicht die Leistungsfähigkeit des Strategy-Musters: Dein OrderProcessor enthält selbst keinerlei Logik zur Berechnung der Versandkosten. Er delegiert die Aufgabe einfach an die Strategie, die ihm übergeben wurde. Dadurch lassen sich problemlos neue Versandarten (wie DroneDelivery) hinzufügen, ohne den Prozessor überhaupt zu ändern!
Probier es selbst
using System;
using Shipping;
class Program
{
public static void Main(string[] args)
{
// Eingabe lesen
string shippingType = Console.ReadLine();
double weight = Convert.ToDouble(Console.ReadLine());
// TODO: Erstelle eine OrderProcessor-Instanz
// TODO: Basierend auf shippingType ("standard", "express" oder "overnight"),
// erstelle die passende Versandstrategie und setze sie auf dem Prozessor
// TODO: Verarbeite die Bestellung und gib die berechneten Kosten aus
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjektinitialisiererWiederholung – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbungs-(:)-SyntaxDas „base“-Schlüsselwort„virtual“- und „override“-SchlüsselwörterVersiegelte KlassenDie „object“-BasisklasseWiederholung – Mitarbeiterhierarchie7Erweiterte Funktionen
Überladen von OperatorenIndexer (this[])ToString()-ÜberschreibungErweiterungsmethodenRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterThread-sicheres SingletonFactory-MusterObserver-Muster (Events)Strategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformKomponente für SpielfigurenFahrzeugvermietungsdienst2Eigenschaften & statische Member
Automatisch implementierte EigenschaftenNur lesbare/schreibbare EigenschaftenStatische Felder & MethodenStatische KlassenMember mit Ausdruckskörpern5Polymorphie & Interfaces
Compile- vs. Laufzeit-PolymorphieInterface vs. abstrakte KlasseMehrere InterfacesExplizite InterfacesUpcasting & DowncastingWiederholung – Formenrechner3Klassenarchitektur
Instanz- vs. statische DatenSchlüsselwörter 'readonly' & 'const'Backing FieldsRückblick – Bankkontenverwaltung6Kapselung
ZugriffsmodifikatorenEigenschaften zur KapselungImplementierung der DatenkapselungMuster für UnveränderlichkeitRückblick – SchülerdatenÜbe selbstständig: Online-C#-Compiler