Pattern Strategy
Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 55 di 70.
Il pattern Strategy è un pattern comportamentale che ti permette di definire una famiglia di algoritmi, incapsulare ciascuno nella propria classe e renderli intercambiabili durante l’esecuzione. Invece di codificare rigidamente il comportamento, inietti la strategia desiderata in un oggetto.
Il pattern è composto da tre parti: un'interfaccia strategia che definisce il contratto dell'algoritmo, classi strategia concrete che implementano comportamenti diversi e una classe contesto che utilizza una strategia:
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);
}
}Il contesto (ShoppingCart) non sa quale metodo di pagamento sta usando: si limita a chiamare Pay() sulla strategia fornita:
var cart = new ShoppingCart();
cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m); // Pagato 99.99 con carta di credito
cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m); // Pagato 49.99 con PayPalIl pattern Strategy elimina la logica condizionale complessa. Aggiungere un nuovo metodo di pagamento significa creare una nuova classe che implementa IPaymentStrategy - non sono necessarie modifiche in ShoppingCart. Questo rende il tuo codice aperto all'estensione ma chiuso alle modifiche.
Sfida
FacileCostruiamo un calcolatore dei costi di spedizione usando il pattern Strategy. I diversi metodi di spedizione hanno algoritmi di tariffazione diversi e il sistema dovrebbe consentire di passare da uno all'altro in fase di esecuzione senza modificare la logica di elaborazione degli ordini.
Organizzerai il codice in tre file:
ShippingStrategy.cs: definisci un'interfacciaIShippingStrategynel namespaceShippingcon un metodoCalculateCost(double weight)che restituisce undouble. Poi crea tre classi concrete per le strategie:StandardShipping- calcola il costo comeweight * 1.5ExpressShipping- calcola il costo comeweight * 3.0 + 5.0(include una tariffa fissa per la spedizione express)OvernightShipping- calcola il costo comeweight * 5.0 + 10.0(servizio premium con una tariffa base più alta)
OrderProcessor.cs: crea una classeOrderProcessornello stesso namespace. Questa è la classe contesto che usa una strategia di spedizione. Dovrebbe avere:- Un campo privato per contenere l'attuale
IShippingStrategy - Un metodo
SetShippingMethod(IShippingStrategy strategy)per cambiare la strategia di spedizione - Un metodo
ProcessOrder(double weight)che usa la strategia attuale per calcolare e restituire il costo di spedizione
- Un campo privato per contenere l'attuale
Program.cs: metti insieme tutti gli elementi creando unOrderProcessore mostrando come puoi cambiare le strategie di spedizione in fase di esecuzione. Lo stesso processore può calcolare i costi usando algoritmi diversi semplicemente cambiando la strategia.
Riceverai due input:
- Il tipo di metodo di spedizione:
standard,expressoppureovernight - Il peso del pacco come numero decimale (ad es.,
4.5)
Crea un OrderProcessor, imposta la strategia di spedizione appropriata in base al tipo di input, quindi elabora l'ordine e stampa il costo calcolato.
Ad esempio, se gli input sono express e 4.5, l'output dovrebbe essere:
18.5Questo dimostra la potenza del pattern Strategy: il tuo OrderProcessor non contiene alcuna logica di calcolo delle spedizioni. Si limita a delegare alla strategia che gli è stata assegnata, rendendo semplice aggiungere nuovi metodi di spedizione (come DroneDelivery) senza modificare affatto il processore!
Provalo tu
using System;
using Shipping;
class Program
{
public static void Main(string[] args)
{
// Leggi l'input
string shippingType = Console.ReadLine();
double weight = Convert.ToDouble(Console.ReadLine());
// TODO: Crea un'istanza di OrderProcessor
// TODO: In base a shippingType ("standard", "express" o "overnight"),
// crea la strategia di spedizione appropriata e impostala sul processore
// TODO: Elabora l'ordine e stampa il costo calcolato
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniNamespace e direttiveIntroduzione a classi e oggettiLa parola chiave "this"Metodi e parametriCampi e proprietàCostruttoriInizializzatori di oggettiRiepilogo - Calcolatrice semplice4Ereditarietà
Sintassi di base dell'ereditarietà (:)La parola chiave 'base'Parole chiave virtual e overrideClassi sealedLa classe base 'object'Riepilogo - Gerarchia dei dipendenti7Funzionalità avanzate
Sovraccarico degli operatoriIndicizzatori (this[])Override di ToString()Metodi di estensioneRiepilogo - Lista personalizzata10Pattern di progettazione Parte 1
Introduzione ai pattern di progettazioneSingleton thread-safePattern FactoryPattern Observer (eventi)Pattern Strategy2Proprietà e membri statici
Proprietà implementate automaticamenteProprietà di sola lettura e di sola scritturaCampi e metodi staticiClassi staticheMembri con corpo di espressione5Polimorfismo e interfacce
Polimorfismo a compile time e runtimeInterfaccia o classe astrattaInterfacce multipleInterfacce espliciteUpcasting e downcastingRipasso: calcolatore di forme8Concetti avanzati di programmazione a oggetti
Composizione invece dell'ereditarietàTipi generici (classi e metodi)Delegati ed eventiAttributi e reflectionIDisposable e istruzione usingNozioni di base sull'iniezione delle dipendenze11Pattern di progettazione, parte 2
Pattern del ComandoPattern dell’AdattatorePattern del DecoratorePattern Template MethodPattern dello StatoPattern Composito3Architettura delle classi
Dati di istanza vs staticiParole chiave 'readonly' e 'const'Campi di supportoRiepilogo - Gestore di conti bancari6Incapsulamento
Modificatori di accessoProprietà per l'incapsulamentoImplementazione dell'occultamento dei datiModelli di immutabilitàRiepilogo - Registri degli studentiEsercitati da solo: Compilatore C# online