Decorator Pattern – extinderea funcționalității fără moștenire în .NET

  • Doru Bulubasa
  • 26 November 2025

În dezvoltarea modernă de software, flexibilitatea este esențială. Aplicațiile evoluează, cerințele se schimbă, iar componentele trebuie adaptate rapid fără a compromite stabilitatea sistemului. Decorator Pattern este unul dintre cele mai elegante și utile modele de design orientat pe obiecte, permițând extinderea comportamentului unui obiect în timpul rulării, fără a utiliza moștenire și fără a modifica structura existentă a clasei.

Acest pattern apare des în scenarii precum logarea, caching-ul, validarea, compresia sau criptarea fluxurilor. În .NET, Decorator este folosit chiar în framework-ul de bază, în special în sistemul de fluxuri (Stream, BufferedStream, GZipStream) și în middleware-urile ASP.NET Core.


1. Ce este Decorator Pattern?

Pe scurt, Decorator:

  • permite adăugarea de funcționalități în mod dinamic unui obiect existent;

  • evită moștenirea excesivă;

  • respectă principiul Open/Closed: clasa este deschisă pentru extindere, dar închisă pentru modificare;

  • menține aceeași interfață pentru obiectele decorate și cele de bază.

Decorator funcționează prin “îmbrăcarea” unui obiect existent într-un obiect suplimentar, care interceptează apelurile și introduce comportamente noi înainte sau după execuția reală.


2. Structura generală

Un Decorator clasic are trei componente:

  1. Component – interfața comună

  2. Concrete Component – implementarea principală

  3. Decorator – clasa abstractă care implementează aceeași interfață și conține componentul decorat

  4. Concrete Decorators – extensiile reale


3. Exemplu simplu în C#: extinderea unui serviciu de mesaje

Presupunem că avem un serviciu care trimite mesaje. Ulterior dorim să adăugăm logare și validare, fără să modificăm implementarea inițială.

Component

public interface IMessageService
{
    void Send(string message);
}

Concrete Component

public class MessageService : IMessageService
{
    public void Send(string message)
    {
        Console.WriteLine($"Sending message: {message}");
    }
}

Decorator abstract

public abstract class MessageServiceDecorator : IMessageService
{
    protected readonly IMessageService _inner;

    protected MessageServiceDecorator(IMessageService inner)
    {
        _inner = inner;
    }

    public virtual void Send(string message)
    {
        _inner.Send(message);
    }
}

Decorator pentru logare

public class LoggingDecorator : MessageServiceDecorator
{
    public LoggingDecorator(IMessageService inner) : base(inner) { }

    public override void Send(string message)
    {
        Console.WriteLine("[LOG] Trimitere mesaj...");
        base.Send(message);
    }
}

Decorator pentru validare

public class ValidationDecorator : MessageServiceDecorator
{
    public ValidationDecorator(IMessageService inner) : base(inner) { }

    public override void Send(string message)
    {
        if (string.IsNullOrWhiteSpace(message))
        {
            Console.WriteLine("Mesaj invalid!");
            return;
        }
        base.Send(message);
    }
}

Utilizare

IMessageService service =
    new LoggingDecorator(
        new ValidationDecorator(
            new MessageService()));

service.Send("Salut din Decorator Pattern!");

Rezultatul:

[LOG] Trimitere mesaj...
Sending message: Salut din Decorator Pattern!

Observăm că funcționalitatea a fost extinsă fără moștenire multiplă sau modificarea implementării originale.


4. Avantaje ale Decorator Pattern

✔ extindere flexibilă și modulară

✔ evită clasele gigantice cu multe responsabilități

✔ permite combinarea comportamentelor în lanț

✔ funcționează excelent în .NET cu middleware, stream-uri, interceptoare


5. Când să folosim Decorator Pattern?

  • când vrei să adaugi funcționalități suplimentare fără a modifica clasa existentă;

  • când ai nevoie de combinarea unor comportamente în mod variabil;

  • când moștenirea duce la o ierarhie prea complicată;

  • când dorești un sistem extensibil în timp real.


6. Decorator în .NET din viața reală

Exemple foarte clare:

  • BufferedStream, GZipStream, CryptoStream → decorează Stream

  • Middleware în ASP.NET Core → fiecare componentă decorează request-ul

  • Decoratori în DI cu Scrutor → wrapping de servicii în runtime

🤖 Întreabă AI despre acest articol

AI Răspuns generat de AI pe baza acestui articol.
AI scrie răspunsul…

Scrie un comentariu

Adresa de mail nu va fi publicata. Campurile obligatorii sunt marcate cu *