Template Method Pattern anstatt if-else?



  • Hallo?
    Ich sagte bereits:

    sinnvolle einfache C++ bespiele zum state pattern finde ich nicht

    unter google finde ich nur umfangreiche und nicht gerade erklärende beispiele.

    Aber gut - damit muss ich wohl leben.



  • Mati schrieb:

    @Bashar:

    Praktisch also im cpp-File. Das ist auch von den Abhängigkeiten her sinnvoller.

    wenn ich gleichzeitig mit Templates arbeite - ist das dan auch möglich?

    Nein, dann natürlich nicht (außer mit export etc. blahblah). Das entscheidende ist, dass der Ctor außerhalb der Klasse base definiert sein muss.

    class Base {
    public:
      Base();
    };
    
    // ich schreib hier die Klassendefinition direkt hin, bei dir wäre ein 
    // #include "derived.h" an dieser Stelle
    class Derived : public Base {
    public:
      Derived() { blub(); }
    };
    
    // jetzt ist Derived erst bekannt und kann konstruiert werden
    Base::Base() {
      new Derived() ...
    }
    


  • Ok, dann versuche ich eine konkrete Frage zu stellen:

    Ich bin mir nicht sicher ob ich missverstanden wurde. Ich will in der main() einen Template - Typ zurückbekommen, der anhand eines int-werts entweder double oder COMPLEX ist.

    Ich kann ja aus der main keine Templates initialisieren. Also sowas geht ja in der main nicht:

    Abstract_Matrix ab_mat;
    
    // 0 für real
    // 1 für complex
    Matrix<T>* matrix = ab_mat.Get_Type(0);
    
    //in der Abstract_Matrix
    
    template <class T>
    class Abstract_Matrix
    {
         public:
    
                T* Get_Type(int c)
                {
                         if (c)
                             return new Matrix<double>;
                         else return new Matrix<COMPLEX>;
                }  
    };
    

    so ist es ja alles schwachsinn.

    Nach diesem Satz:

    This is a clean way for an object to partially change its type at runtime.
    

    Unter diesem Link:
    http://en.wikipedia.org/wiki/State_pattern

    gibt es die folgenden Methoden:

    selectPenTool() {
         currentTool.reset(new PenTool);
       }
    
       selectSelectionTool() {
         currentTool.reset(new SelectionTool);
       }
    

    Allerdings ist mir schleierhaft wie ich denn einen Template-Basierten DrawingController bauen sollte, der seinen Template-Typ von double nach COMPLEX ändert bzw. wechseln braucht er ja nicht mal. Er braucht ihn ja nur zu initialisieren....



  • Wie schon mehrfach angedeutet, mit einem rein Template-basiertem Ansatz kannst du da zur Laufzeit nicht viel machen.

    Davon abgesehen hast du dich mit deinem Matrix-Beispiel, relativ gesehen, kilometerweit von deinem Ausgangsproblem entfernt.
    So kann dir nicht nur keiner wirklich helfen, irgendwann fühlen sich die Leute auch ein wenig verarscht. Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu. Wenn du Hilfe zu deinem konkreten Problem suchst, dann leg endlich mal dar was du überhaupt machen willst.



  • Wie schon mehrfach angedeutet, mit einem rein Template-basiertem Ansatz kannst du da zur Laufzeit nicht viel machen.

    So etwas wollte ich wissen - mehr nicht.

    Davon abgesehen hast du dich mit deinem Matrix-Beispiel, relativ gesehen, kilometerweit von deinem Ausgangsproblem entfernt.
    So kann dir nicht nur keiner wirklich helfen, irgendwann fühlen sich die Leute auch ein wenig verarscht.

    Ich habe geschrieben, dass ich ein weiteres Problem habe, wo ich nicht sicher bin ob es evtl. über Patterns lösbar wäre, evtl. sogar über das TMP. Deshalb hier gepostet.
    Wenn man neue Threads aufmacht wird man angeschnauzt man öffne für dieselben Probleme ständig neue Threads.
    Wenn man in gleichen Threads arbeitet genauso - also was nun?

    Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu.

    Mit so einem Threas käme als Antwort: Schau bei google oder benutze die Suchfunktion. Auf solche Antworten kann ich verzichten - so ein Thread bringt überhaupt nichts.

    Wenn du Hilfe zu deinem konkreten Problem suchst, dann leg endlich mal dar was du überhaupt machen willst.

    Mein konkretes problem habe ich dargestellt. Das kann mir nicht angekreidet werden. Vorgeworden werden kann mir nur, dass ich mich sehr unverständlich ausgedrückt habe.



  • Mati schrieb:

    Ich habe geschrieben, dass ich ein weiteres Problem habe, wo ich nicht sicher bin ob es evtl. über Patterns lösbar wäre, evtl. sogar über das TMP. Deshalb hier gepostet.
    Wenn man neue Threads aufmacht wird man angeschnauzt man öffne für dieselben Probleme ständig neue Threads.
    Wenn man in gleichen Threads arbeitet genauso - also was nun?

    Tatsächlich. Hatte's zuvor nur überflogen - sah so aus als ginge es um das selbe Problem, insbesondere weil's danach wieder nahtlos zum Ursprungsproblem überging.

    Ist halt schon praktischer für verschiedene Fragen verschiedene Threads zu öffnen. Da wird auch sicher niemand meckern.

    Mati schrieb:

    Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu.

    Mit so einem Threas käme als Antwort: Schau bei google oder benutze die Suchfunktion. Auf solche Antworten kann ich verzichten - so ein Thread bringt überhaupt nichts.

    Definiere "so ein Thread". Wenn du nur mit einem "das XY funzt bei mir nich?!!1" ankommst, dann klar, so was wird zerrissen. Ein "Ich habe mir unter [link] das XY-Pattern angeschaut und verstehe [irgendeinen Punkt] nicht" o.ä. wird da ganz anders aufgenommen.

    Mati schrieb:

    Mein konkretes problem habe ich dargestellt. Das kann mir nicht angekreidet werden. Vorgeworden werden kann mir nur, dass ich mich sehr unverständlich ausgedrückt habe.

    Siehe oben. Ich dachte die Matrix-Geschichte gehört irgendwie dazu, ist das eigentliche Problem oder gar nur ein anderes, potentiell unverwandtes Beispiel. 😉



  • Meine Konkrete Frage zum Template Method Pattern ist:

    Wenn eine abgeleitete Klasse nur zusätzlich etwas tun soll, wie bringt man das in das "Skelett" ein?
    Es macht doch wenig Sinn eine dummy-variable anzulegen die im Fall A nicht intialisiert wird und im Fall B schon, diese dann an die virtuelle Fuktion zu übergeben oder?
    Aber andererseits müsste man doch wieder das ganze Skelett virtuell machen, wenn man in einer Version zusätzliche Variablen verwenden will und in der anderen nicht?

    Ich versuche meine Frage an einem pseudo-beispielcode zu erklären:

    class skelett
    {
    public:
      void my_algorithm()
      {
        int* a = NULL;
        init_b();
    
        // hier die funktion:
        a = make_this();
    
        compute(a);
      }
    
       void init_b(//do something) {...};
    
    protected:
         virtual void compute(int* a) = 0;
         virtual int* make_this() = 0;
    };
    
    class FallA : public skelett
    {
    protected:
      virtual int* make_this() { return NULL; }
      virtual void compute(int* a)
       {
             //mache was ohne a zu verwenden
        }
    };
    
    class FallB : public skelett
    {
    protected:
      virtual int* make_this() 
      {
           //initialisiere a 
           a = new int[4]; 
       }
      virtual void compute(int* a)
       {
             //hier mit a irgendwelche sachen machen
        }
    };
    


  • Ja ja. Ich würde jetzt gern was über metasyntaktische Symbole und konstruierte Grenzfälle vom Stapel lassen, aber mir fällt nichts ein.

    Naja. Wie dem auch sein. Mach einfach ein konkretes Beispiel daraus, und ich sage dir, aus meiner Sicht, warum das so OK ist/wie man das richtig bzw. besser umsetzt/warum das Pattern ungeeignet ist.



  • Puh....das ist gar nicht so einfach ein konkretes Beispiel zu machen....

    //in der main wird der algorithmus also das skelett aufgerufen:
    
    					Switch_Algorithm<COMPLEX> o_alg;
    					Spai<COMPLEX>* alg_ptr  = o_alg.Get_Algorithm(opt_level);
    
    					alg_ptr->SPAI_Algorithm(...);
    
    // hier ist meine switch-methode - was besseres ist mir nicht eingefallen als sie in ne eigene Klasse zu packen...
    template <class T>	Spai<T>*
    Switch_Algorithm<T>::Get_Algorithm(const int opt_level)
    {
    	std::cout << "\t    Optimizations for SPAI:\n";
    	switch(opt_level)
    	{
    		case no_opt:
    			return new Spai_Standard<T>();
    		case caching:
    			return new Spai_Caching<T>();
    		// no default case
    	}
    }
    

    Hier das Skelett:

    template <class T>	void
    Spai<T>::SPAI_Algorithm(...)
    {	
    
    	//Iterating over each column
    	for (int col = 0; col < A->n; col++)
    		SPAI_Column(...);
    }
    
    template <class T>	void
    Spai<T>::SPAI_Column(...)
    {
    
    	// Variablen werden angelegt
    
            //HIer sind einige Funktionen vor der for-schleife
    
    	for (int step = -1; step < max_impr_steps; step++)
    	{
    		//hier sind einige funktionen die beide fälle gemeinsam haben
    
                    // HIER!!!!!!!!!!!!!!!!!!!!!!!!!!! will ich jetzt für den Fall B einen
                    // Cache bauen, dass wollte ich über eine virtuelle Methode machen
                    //ABER: Dazu müsste ich ja allgemein einen cache besitzen der auch 
                    // im Fall A da ist aber halt dann NULL oder empty oder so...
                    // An die folgende Submethode sollte dieser Cache 
                   //dann weitergegeben werden, die ja virtuell ist und man dann dort
                   // machen kann was man will
                    Approximative_Solution(...)
    
    		// ....ab hier folgen noch mehrere Fkt-Aufrufe die beide fälle gemeinsam haben
    	}
    
    }
    

    hier Fall A

    template <class T>
    class Spai_Standard : public Spai<T>
    {
    	public:
    
    	private:
    
    	protected:
    
    		virtual void	Approximative_Solution(...);		
    };
    

    //hier Fall B

    template <class T>
    class Spai_Caching : public Spai<T>
    {
    	public:
    
    	private:
    
    	protected:
    
    		virtual void	Approximative_Solution(	...);
    };
    

    Und hier die virtuelle Methode

    template<class T>	void
    Spai_Caching<T>::Approximative_Solution(...)
    {
    	//Hier will ich jetzt einen Cache verwenden, 
           //da wir uns sowieso schon im Fall B befinden 
           //ist das also jetzt kein Problem - nur muss ich 
     //dazu wohl den cache an diese Methode übergeben.
    


  • Lies dir noch einmal einen früheren Post von mir durch.

    Du stellst eine allgemeine Frage zum TMP, und auf die Bitte hin ein sinnvolles Beispiel anzuführen, kehrst du (scheinbar) zu deinem ursprünglichen Problem zurück und lieferst dazu nicht nur keinen Kontext, sondern lässt den interessanten Teil - "//hier sind einige funktionen die beide fälle gemeinsam haben" - komplett aus!

    Ohne zu wissen worum es sich dreht, der Cache ist schlicht kein Teil des Interfaces.

    Aber naja.

    Entweder du legst jetzt dein konkretes Problem - deine Spai Matrix oder was auch immer - verständlich, mit allen relevanten Details dar, oder du hältst dich an das allgemeine Pattern und erbringst dann eine Transferleistung wenn du's verstanden hast. Oder eben auch nicht, musst du wissen.

    Das ist natürlich nur IMAO.



  • Lies dir noch einmal einen früheren Post von mir durch.

    Habe ich gemacht - nur leider beantwortet das nicht meine Frage

    Du stellst eine allgemeine Frage zum TMP, und auf die Bitte hin ein sinnvolles Beispiel anzuführen, kehrst du (scheinbar) zu deinem ursprünglichen Problem zurück

    Was ist denn ein sinnvolles Beispiel? Mehr als meinen reduziert, vereinfachten code und einen ausgedachten vereinfachten Code kann ich nicht bieten!?
    Soll ich jetzt über 5000 Zeilen code hier veröffentlichen?

    und lieferst dazu nicht nur keinen Kontext, sondern lässt den interessanten Teil - "//hier sind einige funktionen die beide fälle gemeinsam haben" - komplett aus!

    Der Teil kann nicht interessant sein, weil das subroutinen sind die von beiden Klassen gleichzeitig verwendet werden. Die sind nicht virtuell sondern in einer ganz anderen Klasse untergebracht. Beide derived-classes (also Spai_Standard und Spai_Caching) benutzen diese einfach. Keine Vererbung kein gar nichts.

    Ohne zu wissen worum es sich dreht, der Cache ist schlicht kein Teil des Interfaces.

    Richtig. Der Cache soll nur zu einer der beiden gehören (also in dem Fall Spai_Caching).

    Entweder du legst jetzt dein konkretes Problem - deine Spai Matrix oder was auch immer - verständlich, mit allen relevanten Details dar,
    oder du hältst dich an das allgemeine Pattern und erbringst dann eine Transferleistung wenn du's verstanden hast. Oder eben auch nicht, musst du wissen.

    Laut Deinen Aussagen ist der Satz von meinem vorletzten Posting:

    Wenn eine abgeleitete Klasse nur zusätzlich etwas tun soll, wie bringt man das in das "Skelett" ein?

    wohl von Dir damit zu beantworten das ich mich nicht ans allgemeine Pattern halte.

    Ich weiß leider nicht mehr was ich noch tun könnte. Ich denke die Frage in dem Posting vor meinem letzten posting ist deutlich genug.



  • Mati schrieb:

    Lies dir noch einmal einen früheren Post von mir durch.

    Habe ich gemacht - nur leider beantwortet das nicht meine Frage

    Es war auch keine Antwort auf deine Frage, sondern eine Hilfestellung wie du die Wahrscheinlichkeit steigerst genau dazu zu kommen. Falls es dir nicht aufgefallen ist.

    Mati schrieb:

    Du stellst eine allgemeine Frage zum TMP, und auf die Bitte hin ein sinnvolles Beispiel anzuführen, kehrst du (scheinbar) zu deinem ursprünglichen Problem zurück

    Was ist denn ein sinnvolles Beispiel? Mehr als meinen reduziert, vereinfachten code und einen ausgedachten vereinfachten Code kann ich nicht bieten!?
    Soll ich jetzt über 5000 Zeilen code hier veröffentlichen?

    Traurig dass man dies auch noch erklären muss: ein Beispiel welches von möglichst minimaler Komplexität ist, so dass es tatsächlich analog zu deinem konkreten Problem ist, ein Beispiel welches sich analysieren lässt: foo, bar und whatever können aüßerst praktisch und sinnvoll sein; wenn die Bezeichner allerdings relevant sind, sind metasyntaktische Symbole (schlag z.B. link auf und schau ob du unter "beliebig" etwas findest. (Tipp: foo == compute, in aller Regel)) nicht allzu hilfreich.

    Mati schrieb:

    und lieferst dazu nicht nur keinen Kontext, sondern lässt den interessanten Teil - "//hier sind einige funktionen die beide fälle gemeinsam haben" - komplett aus!

    Der Teil kann nicht interessant sein, weil das subroutinen sind die von beiden Klassen gleichzeitig verwendet werden. Die sind nicht virtuell sondern in einer ganz anderen Klasse untergebracht. Beide derived-classes (also Spai_Standard und Spai_Caching) benutzen diese einfach. Keine Vererbung kein gar nichts.

    So, du bist "mit Templates bisher erst seit kurzem in Kontakt gekommen", weißt nicht recht was du mit dem Begriff "Template Method Pattern" anfangen sollst, dir sträuben sich nicht die Nackenhaare wenn du Dinge wie " virtuall " von dir gibst, siehst auf das Wesentliche reduzierte Beispiele als "umfangreiche und nicht gerade erklärende beispiele" an, du hast - nichts für ungut - keine Ahnung von Programmdesign und/oder C++, aber willst mir erzählen dass du beurteilen kannst was relevant ist und was nicht? Bring mich mal zum lachen.

    Mati schrieb:

    Ohne zu wissen worum es sich dreht, der Cache ist schlicht kein Teil des Interfaces.

    Richtig. Der Cache soll nur zu einer der beiden gehören (also in dem Fall Spai_Caching).

    Oha. Noch ein neues Wort. "Interface". Oder ist es dir schon einmal über den Weg gelaufen und du weißt schlicht nichts damit anzufangen?

    Mati schrieb:

    Entweder du legst jetzt dein konkretes Problem - deine Spai Matrix oder was auch immer - verständlich, mit allen relevanten Details dar,
    oder du hältst dich an das allgemeine Pattern und erbringst dann eine Transferleistung wenn du's verstanden hast. Oder eben auch nicht, musst du wissen.

    Laut Deinen Aussagen ist der Satz von meinem vorletzten Posting:

    Wenn eine abgeleitete Klasse nur zusätzlich etwas tun soll, wie bringt man das in das "Skelett" ein?

    wohl von Dir damit zu beantworten das ich mich nicht ans allgemeine Pattern halte.

    Ooooh, the Lesekompetenz is [not so] strong in this one.

    Mati schrieb:

    Ich weiß leider nicht mehr was ich noch tun könnte. Ich denke die Frage in dem Posting vor meinem letzten posting ist deutlich genug.

    Mach dir nichts draus: das ist, wie gesagt, alles IMAO, und selbst wenn ich nicht allein da stehe, hier tummeln sich genügend Leute mit Helfersyndrom. Wenn dir das nicht ausreicht, ändere einfach deine Taktik. (linky)



  • So, du bist "mit Templates bisher erst seit kurzem in Kontakt gekommen", weißt nicht recht was du mit dem Begriff "Template Method Pattern" anfangen sollst, dir sträuben sich nicht die Nackenhaare wenn du Dinge wie "virtuall" von dir gibst, siehst auf das Wesentliche reduzierte Beispiele als "umfangreiche und nicht gerade erklärende beispiele" an, du hast - nichts für ungut - keine Ahnung von Programmdesign und/oder C++, aber willst mir erzählen dass du beurteilen kannst was relevant ist und was nicht? Bring mich mal zum lachen.

    das einzige was ich mich im Moment nur noch frage ist:
    Woher man sich das Recht nimmt so über jemanden zu urteilen. Es ist in Ordnung Menschen zurecht zu weisen wenn Sie falsch oder unverständlich posten. Aber Du könntest Dich z.B auch mal fragen warum Dich vielleicht andere Leute die vielleicht "nicht so gut programmieren wie Du" nicht verstehen?
    Leute wie Du haben in einem solchen Forum mit dieser Art von postings meiner Meinung nach nichts verloren.

    Für mich ist der Thread ist geschlossen.


Anmelden zum Antworten