Question

Je ne suis pas sûr de bien comprendre le modèle de méthode de modèle.

Voici mon implémentation simplifiée de ma classe de base :

public abstract class AlgorithmBase
{
    protected void AlgorithmMethod()
    {
        if(!OnSimulationStart())
        {
            OnSimulationEnd(false);
            return;
        }

        if(!DoSomeStep())
        {
            OnSimulationEnd(false);
            return;
        }

        OnSimulationEnd(true);
    }

    protected abstract bool OnSimulationStart();
    protected abstract bool DoSomeStep();
    protected abstract void OnSimulationEnd(bool result);
}

Autant que je sache, la classe de base connaît le flux de l'algorithme et le gère.Le problème est que dans un projet réel, j'ai de nombreuses méthodes abstraites et ce serait bien si je pouvais d'une manière ou d'une autre empêcher de les appeler directement dans les classes dérivées.Il est illisible lorsque plusieurs classes gèrent le flux d’algorithmes.

Était-ce utile?

La solution

Une astuce basée sur l'implémentation explicite d'une interface peut être utilisée pour empêcher les invocations accidentelles d'une méthode requise par l'implémentation de l'algorithme de base.Cependant, il s'agit d'une telle mesure de sécurité qui peut être enfreinte, mais il y a de fortes chances que le développeur sache ce qu'il ferait.

Une interface déclarant les méthodes requises par AlgorithmMethod:

public interface IAlgorithmMethodImpl
{
    bool OnSimulationStart();
    bool DoSomeStep();
    void OnSimulationEnd(bool result);
}

Classe abstraite de base qui utilise cette interface, passée à son constructeur, pour appeler les méthodes requises :

public abstract class AlgorithmBase
{
    protected AlgorithmBase(IAlgorithmMethodImpl impl)
    {
        Impl = impl;
    }

    // can be a property reasonable cases; however, a field 
    // fits well into our scenario
    private IAlgorithmMethodImpl Impl; 

    protected void AlgorithmMethod()
    {
        if(!Impl.OnSimulationStart())
        {
            Impl.OnSimulationEnd(false);
            return;
        }

        if(!DoSomeStep())
        {
            Impl.OnSimulationEnd(false);
            return;
        }

        Impl.OnSimulationEnd(true);
    }

    // no abstract method declarations here — they are provided by 'Impl'
}

Ensuite, la classe d'algorithme spécifique qui hérite de AlgorithmBase utilise une implémentation d'interface explicite pour encapsuler l'implémentation des méthodes nécessaires (comme avec les méthodes abstraites déclarées dans la base) tout en empêchant leur invocation accidentelle :

public class MySuperAlgorithm : AlgorithmBase, IAlgorithmMethodImpl
{
    public MySuperAlgorithm()
        // pass a reference to this instance as the class 
        // that implements the required methods
        : base(this) 
    {
    }

    // explicit implementation of IAlgorithmMethodImpl
    bool IAlgorithmMethodImpl.OnSimulationStart() { ... implementation ... }
    bool IAlgorithmMethodImpl.DoSomeStep() { ... implementation ... }
    void IAlgorithmMethodImpl.OnSimulationEnd(bool result) { ... implementation ... }
}

L'avantage de cette approche - en plus d'éviter l'appel accidentel de méthodes d'implémentation - est que vous pouvez choisir d'encapsuler l'implémentation dans le descendant ou de la décomposer dans une classe distincte.

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