Menu
Coddy logo textTech

Wzorzec strategii

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 55 z 70.

Wzorzec strategii to wzorzec behawioralny, który pozwala zdefiniować rodzinę algorytmów, hermetyzować każdy z nich we własnej klasie i zamieniać je miejscami w czasie działania programu. Zamiast kodować zachowanie na sztywno, wstrzykujesz wybraną strategię do obiektu.

Wzorzec składa się z trzech części: interfejsu strategii definiującego kontrakt algorytmu, konkretnych klas strategii implementujących różne zachowania oraz klasy kontekstu, która korzysta ze strategii:

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);
    }
}

Kontekst (ShoppingCart) nie wie, której metody płatności używa — po prostu wywołuje Pay() na przekazanej strategii:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // Zapłacono 99.99 kartą kredytową

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // Zapłacono 49.99 przez PayPal

Wzorzec Strategii eliminuje złożoną logikę warunkową. Dodanie nowej metody płatności oznacza utworzenie nowej klasy implementującej IPaymentStrategy — nie trzeba wprowadzać żadnych zmian w ShoppingCart. Dzięki temu Twój kod jest otwarty na rozszerzenia, ale zamknięty na modyfikacje.

challenge icon

Wyzwanie

Łatwy

Stwórzmy kalkulator kosztów wysyłki z użyciem wzorca strategii. Różne metody wysyłki mają różne algorytmy wyceny, a system powinien umożliwiać przełączanie się między nimi w czasie działania programu bez zmieniania podstawowej logiki przetwarzania zamówień.

Rozmieścisz kod w trzech plikach:

  • ShippingStrategy.cs: Zdefiniuj interfejs IShippingStrategy w przestrzeni nazw Shipping z metodą CalculateCost(double weight), która zwraca wartość typu double. Następnie utwórz trzy konkretne klasy strategii:
    • StandardShipping – oblicza koszt jako weight * 1.5
    • ExpressShipping – oblicza koszt jako weight * 3.0 + 5.0 (uwzględnia stałą opłatę za ekspresową wysyłkę)
    • OvernightShipping – oblicza koszt jako weight * 5.0 + 10.0 (usługa premium z wyższą opłatą podstawową)
  • OrderProcessor.cs: Utwórz klasę OrderProcessor w tej samej przestrzeni nazw. To klasa kontekstu korzystająca ze strategii wysyłki. Powinna zawierać:
    • Prywatne pole przechowujące bieżący obiekt IShippingStrategy
    • Metodę SetShippingMethod(IShippingStrategy strategy), która zmienia strategię wysyłki
    • Metodę ProcessOrder(double weight), która używa bieżącej strategii do obliczenia i zwrócenia kosztu wysyłki
  • Program.cs: Połącz wszystko, tworząc obiekt OrderProcessor i pokazując, jak można zmieniać strategie wysyłki w czasie działania programu. Ten sam procesor może obliczać koszty przy użyciu różnych algorytmów — wystarczy zmienić jego strategię.

Otrzymasz dwa dane wejściowe:

  • Typ metody wysyłki: standard, express lub overnight
  • Wagę paczki jako liczbę dziesiętną (np. 4.5)

Utwórz obiekt OrderProcessor, ustaw odpowiednią strategię wysyłki na podstawie typu podanego na wejściu, a następnie przetwórz zamówienie i wyświetl obliczony koszt.

Na przykład, jeśli danymi wejściowymi są express i 4.5, wynikiem powinno być:

18.5

To pokazuje możliwości wzorca strategii — obiekt OrderProcessor nie zawiera własnej logiki obliczania kosztów wysyłki. Po prostu deleguje to zadanie wybranej strategii, dzięki czemu można łatwo dodawać nowe metody wysyłki (takie jak DroneDelivery) bez modyfikowania procesora!

Spróbuj swoich sił

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // Wczytaj dane wejściowe
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: Utwórz instancję OrderProcessor

        // TODO: Na podstawie shippingType ("standard", "express" lub "overnight"),
        // utwórz odpowiednią strategię wysyłki i ustaw ją w procesorze

        // TODO: Przetwórz zamówienie i wypisz obliczony koszt
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online