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

Scrie un comentariu

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