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 PayPalWzorzec 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.
Wyzwanie
ŁatwyStwó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 interfejsIShippingStrategyw przestrzeni nazwShippingz metodąCalculateCost(double weight), która zwraca wartość typudouble. Następnie utwórz trzy konkretne klasy strategii:StandardShipping– oblicza koszt jakoweight * 1.5ExpressShipping– oblicza koszt jakoweight * 3.0 + 5.0(uwzględnia stałą opłatę za ekspresową wysyłkę)OvernightShipping– oblicza koszt jakoweight * 5.0 + 10.0(usługa premium z wyższą opłatą podstawową)
OrderProcessor.cs: Utwórz klasęOrderProcessorw 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
- Prywatne pole przechowujące bieżący obiekt
Program.cs: Połącz wszystko, tworząc obiektOrderProcessori 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,expresslubovernight - 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.5To 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
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrznePrzestrzenie nazw i dyrektywyWprowadzenie do klas i obiektówSłowo kluczowe „this”Metody i parametryPola a właściwościKonstruktoryInicjalizatory obiektówPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawowa składnia dziedziczenia (:)Słowo kluczowe 'base'Słowa kluczowe virtual i overrideKlasy sealedBazowa klasa 'object'Powtórzenie – hierarchia pracowników7Zaawansowane funkcje
Przeciążanie operatorówIndeksery (this[])Nadpisywanie ToString()Metody rozszerzającePodsumowanie – własna lista10Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychSingleton bezpieczny wątkowoWzorzec fabrykiWzorzec obserwatora (zdarzenia)Wzorzec strategii2Właściwości i składowe statyczne
Właściwości automatyczneWłaściwości tylko do odczytu i zapisuPola i metody statyczneKlasy statyczneSkładowe z ciałem wyrażeniowym5Polimorfizm i interfejsy
Polimorfizm czasu kompilacji a czasu wykonaniaInterfejs a klasa abstrakcyjnaWiele interfejsówJawne implementowanie interfejsówRzutowanie w górę i w dółPowtórka — kalkulator kształtów8Zaawansowane koncepcje OOP
Kompozycja zamiast dziedziczeniaTypy generyczne (klasy i metody)Delegaty i zdarzeniaAtrybuty i refleksjaIDisposable i instrukcja usingPodstawy wstrzykiwania zależności11Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu3Architektura klas
Dane instancji a dane statyczneSłowa kluczowe 'readonly' i 'const'Pola zapasowePowtórzenie — menedżer kont bankowych6Hermetyzacja
Modyfikatory dostępuWłaściwości w hermetyzacjiImplementacja ukrywania danychWzorce niezmiennościPowtórka — dane studentów9Argumenty zmiennej liczby
Słowo kluczowe „params”Parametry opcjonalneArgumenty nazwanePrzeciążanie metodPoćwicz samodzielnie: Kompilator C# online