Web Log di Adrian Florea

"You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
posts - 440, comments - 2715, trackbacks - 3944

My Links

Archives

Post Categories

Image Galleries

.RO Blogs

.RO People

.RO Sites

Blogs

Furls

Links

vinCitori

Il pattern Decorator e la decorazione con un extension method generico

Stamattina, al corso che sto tenendo di architettura base, ho presentato ai ragazzi il classico pattern Decorator per servirci poi nell'implementare i vari servizi di validazione, logging, caching, etc., come decoratori di un repository, ispirato da questo post di Ayende. Uno di loro mi ha chiesto se si poteva scrivere il corpo della CreateComponent in modo ancora piu' usabile. E mi e' venuta l'idea di utilizzare un extension method generico fluente, tanto per introdurli un po' anche nel mondo di C# 3.0

Partiamo dall'implementazione standard del pattern:

using System;

public interface IComponent {
    void Operation();
}

public class ConcreteComponent : IComponent {
    public void Operation() {
        Console.WriteLine("ConcreteComponent");
    }
}

public abstract class Decorator : IComponent {
    private readonly IComponent component;

    protected Decorator(IComponent component) {
        if (component == null) throw new ArgumentNullException("component");
        this.component = component;
    }

    public virtual void Operation() {
        this.component.Operation();
    }
}

public class ConcreteDecoratorA : Decorator {
    public ConcreteDecoratorA(IComponent component) : base(component) { }

    public override void Operation() {
        Console.WriteLine("ConcreteDecoratorA");
        base.Operation();
    }
}

public class ConcreteDecoratorB : Decorator {
    public ConcreteDecoratorB(IComponent component) : base(component) { }

    public override void Operation() {
        Console.WriteLine("ConcreteDecoratorB");
        base.Operation();
    }
}

class Program {
    public static IComponent CreateComponent() {
        return
            new ConcreteDecoratorB(
            new ConcreteDecoratorA(
            new ConcreteComponent()));

    }

    static void Main() {
        IComponent component = CreateComponent();
        component.Operation();
    }
}

Questo snippet quindi stampa:

ConcreteDecoratorB
ConcreteDecoratorA
ConcreteComponent

a console. L'idea per modificare il metodo CreateComponent e' semplice: se definiamo una classe statica ComponentExtension contenente un'extension method generico come di seguito:

public static class ComponentExtension {
    public static Decorator DecorateWith<T>(this IComponent component) where T : Decorator {
        return (T)Activator.CreateInstance(typeof(T), component);
    }
}

il metodo CreateComponent diventa:

public static IComponent CreateComponent() {
    return new ConcreteComponent()
            .DecorateWith<ConcreteDecoratorA>()
            .DecorateWith<ConcreteDecoratorB>();

}

che, a mio parere, e' piu' espressivo. Che ne dite?

Print | posted on giovedì 29 novembre 2007 04:47 | Filed Under [ Pattern Dappertutto GUISA ]

Powered by:
Powered By Subtext Powered By ASP.NET