Design Patterns si widderverwendbar Léisunge fir heefeg Problemer. Si si keng Copy-Paste-Schabloune — si sinn Iddien, déi een un seng eege Situatioun upasst. Dëse Guide geet duerch zéng vun de nëtzlechsten, gruppéiert no hirer Roll.
Strategy (Strategie)
D'Iddi: en Algorithmus zur Laufzäit wielen, ouni de Code z'änneren, deen en oprifft.
Denkt un eng Bezuel-Säit: de Client kann mat Kaart, PayPal oder Iwwerweisung bezuelen. All Optioun ass eng aner Strategie hannert dem selwechte Knäppchen.
public interface IPaymentStrategy
{
void Pay(decimal amount);
}
public class CreditCardPayment : IPaymentStrategy
{
public void Pay(decimal amount) => Console.WriteLine($"Paid {amount} by card");
}
public class PayPalPayment : IPaymentStrategy
{
public void Pay(decimal amount) => Console.WriteLine($"Paid {amount} via PayPal");
}
public class Checkout
{
private readonly IPaymentStrategy _strategy;
public Checkout(IPaymentStrategy strategy) => _strategy = strategy;
public void Complete(decimal amount) => _strategy.Pay(amount);
}Decorator (Dekorateur)
D'Iddi: engem Objet Verhalen derbäiginn, andeems een en a Schichten ëmwéckelt.
Wéi ee Kaffi mat Extraen: een fänkt mat engem Espresso un a schicht Mëllech, Zocker oder Karamell drop, ouni den Espresso selwer z'änneren.
public interface ICoffee
{
string Description { get; }
decimal Cost { get; }
}
public class Espresso : ICoffee
{
public string Description => "Espresso";
public decimal Cost => 2.00m;
}
public class MilkDecorator : ICoffee
{
private readonly ICoffee _inner;
public MilkDecorator(ICoffee inner) => _inner = inner;
public string Description => _inner.Description + ", milk";
public decimal Cost => _inner.Cost + 0.50m;
}Observer (Observateur)
D'Iddi: en Objet informéiert méi Lauschterer, wann eppes sech ännert.
Wéi en Newsletter: d'Leit abonnéieren sech, an all kritt en Update, wann eng nei Editioun erauskënnt.
public interface IListener
{
void Notify(string message);
}
public class NewsFeed
{
private readonly List<IListener> _listeners = new();
public void Subscribe(IListener listener) => _listeners.Add(listener);
public void Publish(string message) =>
_listeners.ForEach(listener => listener.Notify(message));
}Chain of Responsibility (Verantwortungskette)
D'Iddi: eng Ufro laanscht eng Kette vun Handler weiderginn, bis een se behandelt.
Wéi de Clientssupport: en Ticket gëtt Niveau fir Niveau eskaléiert, bis een e léise kann. All Handler entscheet, ob en d'Ufro behandelt oder weidergëtt.
public interface IHandler
{
IHandler SetNext(IHandler handler);
void Handle(string request);
}
public abstract class BaseHandler : IHandler
{
private IHandler? _next;
public IHandler SetNext(IHandler handler)
{
_next = handler;
return handler;
}
public virtual void Handle(string request)
{
_next?.Handle(request);
}
}
public class AuthHandler : BaseHandler
{
public override void Handle(string request)
{
if (request.StartsWith("auth"))
{
Console.WriteLine("Auth passed");
base.Handle(request);
}
else
{
Console.WriteLine("Auth failed — stop");
}
}
}
public class LoggingHandler : BaseHandler
{
public override void Handle(string request)
{
Console.WriteLine($"Logging: {request}");
base.Handle(request);
}
}
var logging = new LoggingHandler();
var auth = new AuthHandler();
logging.SetNext(auth);
logging.Handle("auth:user-42");All Handler kennt nëmmen deen nächsten, sou datt d'Kette ëmgeordert oder erweidert ka ginn, ouni déi existéierend Handler z'änneren.
Singleton
D'Iddi: garantéieren, datt et genee eng Instanz vun enger Klass gëtt.
Wéi eng eenzeg Astellungsdatei fir eng App — jidderee liest déi selwecht.
public sealed class Configuration
{
public static Configuration Instance { get; } = new Configuration();
private Configuration() { }
public string AppName => "MyApp";
}Facade (Fassad)
D'Iddi: e komplext System hannert enger einfacher Entrée verstoppen.
Wéi den Zündschlëssel vun engem Auto: een dréint ee Schlëssel a vill Deeler schaffen zesummen ënnendrënner.
public class OrderFacade
{
private readonly PaymentService _payment = new();
private readonly InventoryService _inventory = new();
public void PlaceOrder(Order order)
{
_payment.Charge(order);
_inventory.Reserve(order);
}
}Builder (Monteur)
D'Iddi: e komplext Objet Schrëtt fir Schrëtt bauen, amplaz mat engem risege Konstruktor.
Wéi ee personaliséierte Burger bestellen: een wielt d'Brout, de Kéis, d'Extraen — an da gëtt zesummegebaut.
public class Burger
{
public bool Cheese { get; set; }
public bool Bacon { get; set; }
}
public class BurgerBuilder
{
private readonly Burger _burger = new();
public BurgerBuilder AddCheese() { _burger.Cheese = true; return this; }
public BurgerBuilder AddBacon() { _burger.Bacon = true; return this; }
public Burger Build() => _burger;
}Adapter (Adaptateur)
D'Iddi: zwee inkompatibel Interfaces zesumme schaffe loossen.
Wéi e Reesstecker-Adapter, dee äre Ladegerät an eng auslännesch Steckdous passt.
public interface IShape
{
double Area();
}
public class LegacyRectangle
{
public double Width { get; set; }
public double Height { get; set; }
}
public class RectangleAdapter : IShape
{
private readonly LegacyRectangle _rect;
public RectangleAdapter(LegacyRectangle rect) => _rect = rect;
public double Area() => _rect.Width * _rect.Height;
}MVC (Model-View-Controller)
D'Iddi: d'Donnéeën, d'Duerstellung an d'Steierungslogik trennen.
De Model hält d'Donnéeën, d'View weist se un, an de Controller reagéiert op d'Aktiounen vum Benotzer.
public class User
{
public string Name { get; set; } = "Olivier";
}
public class UserController
{
public string GetUserName() => new User().Name;
}MVVM (Model-View-ViewModel)
D'Iddi: d'View direkt un e ViewModel bannen, sou datt d'Interface sech automatesch aktualiséiert, wann d'Donnéeë sech änneren.
Beléift an Desktop- a Mobil-Applikatiounen: ee Klick ännert eng Propriétéit an den Ecran spigelt dat, ouni manuell Verdrotung.
public class CounterViewModel : INotifyPropertyChanged
{
private int _count;
public int Count
{
get => _count;
set { _count = value; OnPropertyChanged(); }
}
public void Increment() => Count++;
// INotifyPropertyChanged implementation omitted for brevity
}CQRS (Trennung vu Kommando an Ufro)
D'Iddi: d'Schreiwen (Kommandoen) vum Liesen (Ufroen) trennen.
Liesen a Schreiwen brauchen dacks ënnerschiddlech Modeller a Späicheren. Se ze trennen hält all Säit einfach a skaléierbar.
public record CreateOrderCommand(int Id, decimal Total);
public record GetOrderQuery(int Id);
public class CreateOrderHandler
{
public void Handle(CreateOrderCommand command) { /* save the order */ }
}
public class GetOrderHandler
{
public Order Handle(GetOrderQuery query) => /* load the order */ null!;
}Event Sourcing (Event-Sourcing)
D'Iddi: all Zoustandsännerung als immutabel Event späicheren, an den aktuellen Zoustand nei opbauen, andeems een dës Eventen nei ofspillt.
Amplaz deen aktuelle Saldo ze späicheren, späichert Dir « 100 ageluecht », « 40 ofgehuewen ». De Saldo ass eng Projektioun, déi Dir zu all Moment nei bereche kënnt.
public interface IEvent { }
public record AccountOpened(Guid AccountId, string Owner) : IEvent;
public record MoneyDeposited(Guid AccountId, decimal Amount) : IEvent;
public record MoneyWithdrawn(Guid AccountId, decimal Amount) : IEvent;
public class Account
{
public Guid Id { get; private set; }
public decimal Balance { get; private set; }
public void Apply(IEvent @event)
{
switch (@event)
{
case AccountOpened e:
Id = e.AccountId;
break;
case MoneyDeposited e:
Balance += e.Amount;
break;
case MoneyWithdrawn e:
Balance -= e.Amount;
break;
}
}
}// load = replay the history
var account = new Account();
foreach (var @event in eventStore.Load(accountId))
{
account.Apply(@event);
}Event Sourcing gëtt Iech eng komplett Audit-Spur, mécht den Zoustand reproduzéierbar a passt natierlech mat CQRS zesummen — mee et kascht méi Späicher a Komplexitéit.
Zum Schluss
Dir wäert net all Pattern all Dag benotzen — awer se erëmzefannen hëlleft Iech, de Code vun aneren ze liesen, iwwer Designen kloer ze diskutéieren an dat richtegt Handwierksgeschir ze wielen, wann e Problem Iech vertraut virkënnt.