Matthieu Mezil
L’objet, c’est beau
Le développement orienté objet peut être apparenté, osons le mot, à une forme d’art. Cependant, avant de devenir un « artiste » de l’objet, il y a plusieurs notions à maîtriser. A travers cet article, nous allons en aborder quelques-unes.
Par Matthieu Mezil publié le 27/04/2009 à 07:10, lu 1671 fois, 10 pages
 3 | Le design pattern Composite
Dans les besoins énoncés au début, nous avions émis le souhait de pouvoir combiner les traitements. Pour cela, nous allons utiliser le design pattern Composite.
Voici la définition de ce pattern proposée par Wikipedia :
En programmation objet, un objet composite est constitué d'un ou de plusieurs objets similaires (ayant des fonctionnalités similaires). L'idée est de manipuler un groupe d'objets de la même façon que s'il s'agissait d'un seul objet. Les objets ainsi regroupés doivent posséder des opérations communes, c'est-à-dire un "dénominateur commun".
Dans le cadre de notre implémentation, il faut utiliser une classe chargée de piloter l’ensemble des traitements (dans notre cas la classe CompositeStringsTransform). Cette classe contiendra une collection de IStringsTransform et implémentera elle-même l’interface IStringsTransform ce qui en fera une classe de traitement comme les autres. L’implémentation de l’interface IStringsTransform va simplement agréger le résultat de chacun des traitements contenus dans la collection de traitement. Ainsi, nous pourrons concaténer autant de traitement que nous le souhaitons.

public interface IStringsTransform

{

    IEnumerable<string> Do(IEnumerable<string> lines);

}

 

internal class CompositeStringsTransform : IStringsTransform

{

    private List<IStringsTransform> _transforms = new List<IStringsTransform>();

 

    public CompositeStringsTransform(IEnumerable<IStringsTransform> transforms)

    {

        _transforms.AddRange(transforms);

    }

    public CompositeStringsTransform(params IStringsTransform[] transforms)

        : this((IEnumerable<IStringsTransform>)transforms)

    {

    }

 

    public List<IStringsTransform> Transforms

    {

        get { return _transforms; }

    }

 

    public IEnumerable<string> Do(IEnumerable<string> lines)

    {

        foreach (var transform in Transforms)

            lines = transform.Do(lines);

        return lines;

    }

 

    public override string ToString()

    {

        var sb = new StringBuilder();

        foreach (var transform in Transforms)

        {

            sb.Append(" & ");

            sb.Append(transform);

        }

        return sb.ToString().Substring(3);

    }

}

 

public abstract class PerStringTransformBase : IStringsTransform

{

    protected PerStringTransformBase()

    {

    }

 

    public IEnumerable<string> Do(IEnumerable<string> lines)

    {

        Init();

        foreach (string line in lines)

            yield return Do(line);

    }

 

    protected abstract string Do(string line);

 

    protected virtual void Init()

    {

    }

}

 

public class InvertCharsPerStringTransform : PerStringTransformBase

{

    internal InvertCharsPerStringTransform()

    {

    }

 

    protected override string Do(string line)

    {

        char[] lineChars = line.ToCharArray();

        Array.Reverse(lineChars);

        return new string(lineChars);

    }

 

    public override string ToString()

    {

        return TransformResources.InvertCharsPerStringTransform;

    }

}

 

public class NumberPerStringTransform : PerStringTransformBase

{

    private int _cpt = 0;

 

    internal NumberPerStringTransform()

    {

    }

 

    protected override string Do(string line)

    {

        return string.Concat((++_cpt).ToString("000"), " : ", line);

    }

 

    protected override void Init()

    {

        base.Init();

        _cpt = 0;

    }

 

    public override string ToString()

    {

        return TransformResources.NumberPerStringTransform;

    }

}

 

public static class Transforms

{

    private static List<IStringsTransform> _transforms;

    public static List<IStringsTransform> TransformsAllowed

    {

        get

        {

            if (_transforms == null)

                _transforms = new List<IStringsTransform>()

        {

            new NumberPerStringTransform(),

            new InvertCharsPerStringTransform(),

            new CompositeStringsTransform(

                new NumberPerStringTransform(),

                new InvertCharsPerStringTransform()),

            new CompositeStringsTransform(

                new NumberPerStringTransform(),

                new InvertCharsPerStringTransform(),

                new NumberPerStringTransform(),

                new InvertCharsPerStringTransform())

        };

            return _transforms;

        }

    }

}

Le gros avantage avec cette implémentation est que chaque classe a un rôle bien précis. Chaque classe de traitement ne sert qu’au traitement et c’est la classe CompositeStringsTransform qui va se charger de piloter les compositions de traitements.
Tous les besoins sont maintenant couverts. Cependant, ce n’est pas fini.
 
» Démarrer une discussion
 
Discussion démarée par killscores le 28/04/2009 à 17:06, 3 commentaire(s).