Question

Il me semble être mentalement coincé dans un dilemme motif Flyweight.

Tout d'abord, disons que j'ai un type jetable DisposableFiddle et une FiddleFactory usine:

public interface DisposableFiddle : IDisposable
{
    // Implements IDisposable
}

public class FiddleFactory
{
    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns a newly created fiddle.
    }
}

Alors, à mon avis, il est tout à fait clair au client de FiddleFactory que l'usine ne revendique pas la propriété du violon créé et qu'il est le violon lorsque vous avez terminé la responsabilité du client de disposer avec.

Cependant, disons plutôt que je veux partager entre les clients tripote en utilisant le modèle Flyweight:

public class FiddleFactory
{
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;        

    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns an existing fiddle if a corresponding s is found,
        // or a newly created fiddle, after adding it to the dictionary,
        // if no corresponding s is found.
    }
}

Alors je me sens moralement obligé de rendre l'usine elle-même à usage unique, car il crée les vièles et conserve des références à leur disposition pendant toute leur durée de vie. Mais cela poserait des problèmes aux clients qui supposaient qu'ils possédaient les vièles et devrait donc les disposer.

Le problème est en fait que j'appelle la FiddleFactory usine au lieu de, disons, FiddlePool, et la méthode « création » CreateFiddle au lieu de GetFiddle? Comme ceci:

public class FiddlePool : IDisposable
{
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;        

    public DisposableFiddle GetFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns an existing fiddle if a corresponding s is found,
        // or a newly created fiddle, after adding it to the dictionary,
        // if no corresponding s is found.
    }

    // Implements IDisposable
}

Ensuite, il est plus clair au client qu'il va pas propriétaire du violon retourné et il est de la responsabilité de la piscine pour éliminer les vièles.

Ou peut-il être résolu facilement que la documentation sage?

Y at-il un moyen de sortir du dilemme? Y at-il même un dilemme? : -)

Était-ce utile?

La solution

Je vois deux façons de sortir de ce problème:

  • ThreadPool style : redessiner les classes afin que le FiddlePool fournit une interface pour faire des choses fiddly. La piscine ne remet pas les instances de Fiddle parce qu'il a une méthode FiddlePool.PlayFiddle à la place. Depuis la durée de vie des contrôles de la piscine de violon, il est responsable de l'élimination d'entre eux.

  • SqlConnection style : modifier la méthode de Éliminez public Fiddle pour qu'il revienne vraiment juste à la piscine tripote violon (qui la classe violon encapsule). En interne, la piscine violon prend soin de vraiment libérer des ressources à usage unique.

Autres conseils

Je suis d'accord avec votre deuxième avis. La terminologie « pool » et « Get » ne font les choses plus claires pour le consommateur. Cependant, il ne fait toujours pas les choses assez claires, et la documentation doit toujours être ajoutée pour assurer une compréhension complète, valide.

Vous devriez faire quelque chose de plus qu'une simple documentation et de nommer des méthodes pour dire aux clients de ne pas appeler disposer. En réalité, il serait préférable d'avoir les clients appellent donc faire que de céder de la mode d'utilisation. Prenez un peu de direction de nos pools de connexions de base de données sont construites.

Les pools de base de données un bouquet de connexions qui sont eux-mêmes conscients piscine. code d'appel crée une connexion, l'ouvre, et appelle à proximité (Éliminez) à ce sujet. Le code d'appel ne sait même pas vraiment si elle est mis en commun ou non, tout cela est géré en interne par la classe de connexion. Avec une connexion mis en commun, appelant Open () est ignoré si la connexion est déjà ouverte. Fermer () / Dispose () est appelée et dans le cas d'une connexion mis en commun cela renvoie en fait la connexion à la piscine au lieu de le fermer.

Vous pouvez faire la même chose en créant une classe PooledFiddle qui remplace Dispose et renvoie l'objet à la piscine. Idéalement, le client aurait même pas de savoir qu'il est un Fiddle mis en commun.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top