Template Method Pattern richtige Wahl?



  • Servus, ich will grob gesagt folgendes erreichen: Ich habe im Prinzip und grob gesagt ein sehr kurzes Programmskelett welches nur aus einer for-schleife besteht die in dieser for-schleife eine Routine aufgerufen wird. Diese Routine soll jedoch abhängig von den übergebenen parametern einen anderen Algorithmus ausführen. Ich habe bisher ein Template Method Pattern benutzt - bin aber nicht schlüssig ob es

    a) eine sinnvolle und gute Wahl ist
    b) ich es auf eine saubere Art gemacht habe.

    Zusätzlich habe ich eine weitere Frage wie ich denn in Switch_Algorithm was ja template-basiert aufgebaut ist eine template-spezialisierung realisieren kann von einem algorithmus von dem nur eine spezielle typ-abhängige implementierung existiert. So wie ich es unten darstelle geht es - ist aber wie ich finde seltsam...

    Ich werde im Folgenden den Code dazu liefern mit kurzen Kommentaren dazu und wäre froh wenn ihr Stellung dazu nehmen könntet.

    // class Skelet.h
    template <class T>
    class Skelet
    {
        public:
    
            virtual     ~Skelet<T>(){ }
    
            void        Skelet_Alg(...);
    
        protected:
    
            virtual void        foo(...) = 0;
    };
    
    // class Skelet.imp
    template <class T>  void
    Skelet<T>::Skelet_Alg(...)
    {   
    
        //Iterating
        for (...)
            foo(...);
    }
    
    // Einer der Algorithmen die das Skelett implementieren - die anderen 
    // Algorithmen sind von der struktur her identisch - nur unterscheiden sich ihre
    // berechnungsweise
    template <class T>
    class Alg_Caching : public Skelet<T>
    {
        public:
    
            Alg_Caching();
    
            ~Alg_Caching();    
    
        protected:
            virtual void    foo(...);
    };
    
    //und hier die Implementierung von Alg_Caching.imp
    template <class T>  void
    Alg_Caching<T>::foo(...)
    {
       // do something special - alg_caching
    }
    

    Soweit hoffentlich ist die struktur klar. Zur instantiierung des richtigen Algorithmuses mache ich folgendes worüber ich mir bis heute nicht im klaren bin ob das eben sauber ist bzw. wie man es besser machen könnte:

    Hier mal der teil der main in dem ich in den jeweiligen algorithmus
    switche. Dies geschieht mitHilfe einer id die vorher berechnet wurde:

    // dies geschieht in der main z.B. irgendwo...
       Switch_Algorithm<double> o_alg;
       Skelet<double>* alg_ptr  = o_alg.Get_Algorithm(id);
       alg_ptr->Skelet_Alg(...);
    

    Und hier Switch_Algorithm.*:

    // hier der header
    template <class T>
    class Switch_Algorithm
    {
        public:
    
            Skelet<T>*        Get_Algorithm(  const int opt_level);
    
            void            Set_Spec(Skelet<double>*& Templ_Spec...);
    
            void             Set_Spec(Skelet<int>*& Templ_Spec,...);
    };
    
    //hier die implementierung
    template <class T>  Skelet<T>*
    Switch_Algorithm<T>::Get_Algorithm( const int opt_level)
    {
        switch(opt_level)
        {
            case no_opt:
                return new Alg_one<T>();
            case caching:
                return new Alg_Caching<T>();
             //weitere case-fälle
            case alg_special:
               Skelet<T>* Templ_Spec = NULL;
               Set_Spec(Templ_Spec, ...);
               return Templ_Spec; 
        }
        //dirty - suppress annoying Warning message
        return NULL;
    }
    
    //und hier die template spezialisierungen - ich weiß nicht wie ich das verbinden // kann.
    
    template <> void
    Switch_Algorithm<double>::Set_Spec(Skelet<double>*& Templ_Spec...)
    {
    
         Templ_Spec = new Bar(...);
    }
    
    template <> void
    Switch_Algorithm<type_a>::Set_Spec(Skelet<int>*& Templ_Spec,...)
    {
        Templ_Spec = NULL;
    }
    

    Ich setze als für die Template spezialisierung den Pointer auf Null falls die implementierung nicht existiert. So kompiliert der code und ich fange vorher diesen fall ab. Die Anwendung wird also nie in den 'int'-spezialsierungs-teil kommen. Doch ich glaube nicht dass das sauber ist. Wie kann ich denn aus dem switch statement die template-spezialisierung definieren?

    Und auch wichtig: Ist diese verwendung über switch_algorithm sauber für eine instantiierung der verschiedenen algorithmen?

    Merci



  • Klingt ein bisschen mehr nach dem Strategy-Pattern was du vorhast...



  • hmm...ja ich habs mir gerade angeschaut das strategy-pattern - sieht tatsächlich irgendwie ähnlich aus zu dem was ich vorhab. Wo liegt denn dann der Unterschied zwischen Template Method Pattern und Strategy Pattern? Dennoch würde ich gern meinen ersten Post beantwortet bekommen mit meinen fragen noch - danke euch schon mal!



  • derHeinzi schrieb:

    hmm...ja ich habs mir gerade angeschaut das strategy-pattern - sieht tatsächlich irgendwie ähnlich aus zu dem was ich vorhab. Wo liegt denn dann der Unterschied zwischen Template Method Pattern und Strategy Pattern? Dennoch würde ich gern meinen ersten Post beantwortet bekommen mit meinen fragen noch - danke euch schon mal!

    Template Method ist dafür da, wenn du einen Kern hast der immer gleich ist. zB du lockst wichtige Resourcen am Anfang und gibst sie am Ende des Algos wieder frei. Oder ähnliches - jedenfalls hast du fixen Code der bei jedem Algo gleich ist. Template Method ermöglicht dir dann Teile des Algos anzupassen.

    Strategy dagegen ermöglicht es dir Algorithmen komplett auszutauschen.



  • *push


Anmelden zum Antworten