Fabrik-Muster



  • Hallo,
    irgendwie habe ich einen Knoten in der Hirnwindung was das Fabrik-Muster angeht.
    Baut die Fabrik Objekte von einer Subklasse oder ist sie unabhängig?
    Ich habe da schon was aber das fühlt sich schei... an!
    Also

    #
    class BC{
      static BC* createsub(string& type)const{
        return new CC(value von type); //Vereinfacht ausgedrückt!
      }
      /.../
    };
    class CCa:public BC{/.../};
    class CCb:public BC{/.../};
    class CCc:public BC{/.../};
    
    class Factory{
      BC* bc=NULL;
      public:
      Factory ( string& type="a" )const{
        bc=BC::createsub( type );
      }
      ~Factory(){
        delete bc;
      }
      bc* getcc(){return bc;}
    };
    
    int main (void) {
      Factory=fac("b");
      BC &cc=*fac.getcc();
      cc.whatever();
    }
    

    Funktionieren tut das ja! Objekte werden angelegt und gelöscht, aber es ist irgendwo falsch, dass weiss ich! Nur wo? 😕

    Vielen dank für Hinweise!

    Bis dann...
    Peanut



  • kannst du bitte dein problem etwas deutlicher beschreiben? ich versteh zumindest grad überhauptnicht
    - auf was du hinauswillst
    - wo dein fehler liegt
    - ob überhaupt einfehler vorliegt
    - du einen vorschlag bzgl. besserem design willst



  • Original erstellt von Korbinian:
    **
    - du einen vorschlag bzgl. besserem design willst**

    Das trifft es!
    Sorry, war etwas confused als ich geschrieben habe!

    Also wie gesagt, funktionieren tut das, aber sowohl:

    Factory=fac("b");
    BC &cc=*fac.getcc();
    cc.whatever();
    

    als auch

    Factory=fac("b");
    fac.getcc()->whatever();
    

    sehen Schei... aus.
    Ich hätte gerne:

    foo bar("b");
    bar.whatever(); //ruft CCB::whatever(*this) auf
    


  • wo ist das problem?

    #include <iostream>
    using namespace std;
    class BaseClass {
        public:
            virtual void tu_was() = 0; // rein virtuelle klasse
    };
    
    class Container1 : public BaseClass {
        public:
            virtual void tu_was() { cout << "Ich bin ein Containter1" << endl; }
    };
    
    class Container2 : public BaseClass {
        public:
            virtual void tu_was() { cout << "Ich bin ein Containter2" << endl; }
    };
    
    class Container3 : public BaseClass 
    {
        public:
            virtual void tu_was() { cout << "Ich bin ein Containter3" << endl; }
    };
    
    class Fabrik {
        private:
            BaseClass *container;
        public:
            Fabrik() { container = NULL; } 
            ~Fabrik() { delete container; }
            bool AddContainer1()
            { 
                if (!container) { container = new Container1; return true; }
                else return false;
            } 
            bool AddContainer2()
            { 
                if (!container) { container = new Container2; return true; }
                else return false;
            } 
            bool AddContainer3()
            { 
                if (!container) { container = new Container3; return true; }
                else return false;
            } 
            void rufe_tu_was() { if (container) container->tu_was(); }
    };
    
    int main ()
    {
        Fabrik f1, f2, f3;
        f1.AddContainer1();
        f2.AddContainer2();
        f3.AddContainer3();
        f1.rufe_tu_was();
        f2.rufe_tu_was();
        f3.rufe_tu_was();
    }
    
    Output:
    > Ich bin Container1
    > Ich bin Container2
    > Ich bin Container3
    

    wars das was du wolltest? das schimpft sich polymorphie 🙂 lies dir mal bisshcen was dazu durch



  • Original erstellt von Korbinian:
    **
    wars das was du wolltest? das schimpft sich polymorphie 🙂 lies dir mal bisshcen was dazu durch**

    Ähh die Polymorphie hatte ich auch schon! X.whatever() wird aus der entsprechenden Sub-Klasse aufgerufen.
    Du hast mein Problem aber dennoch gelöst!:p
    Ich war nicht auf die Idee mit dem AddContainer1() gekommen. Was noch unschön ist , ist die strikte delegation mit

    void rufe_tu_was() { if (container) container->tu_was(); }
    

    Kann man nicht alle aufrufe von Memberfunktionen transparent weiterleiten? Ich habe da den operator() im Kopf aber den habe ich noch nicht wirklich vollständig verstanden. 😞

    Auf jeden Fall schon mal besten Dank



  • bist du dir sicher das die klasse Factory heissen soll? kommt mir ehr vor wie eine art smart_pointer

    boost::shared_ptr<BC> b( BC::createsub( "a" ) );
    

    würde ähnliches verhalten haben und du würdes dir etwas komplexität sparen

    Factory sollte eigentlich die arbeit von BC::createsub machen,

    class BC
    {
        virtuel ~BC() {}
        virtuel BC * clone() = 0;
    };
    
    class CCa:public BC
    {    
        virtuel BC * clone()
        {
            return new CCa( *this );
        }   
    };
    
    class CCb:public BC
    {    
        virtuel BC * clone()
        {
            return new CCb( *this );
        }   
    };
    
    class CCc:public BC
    {    
        virtuel BC * clone()
        {
            return new CCc( *this );
        }   
    };
    
    class Factor
    {
    public:
        void reg(boost::shared_ptr<BC> p, const string & name)
        {
            assert(m_.find( name ) == m_.end()); 
            // name wurde schon registriert
            // kommt auf dein programm an ob hier ein assert reicht
            m_[name] = p;
        }
    
        boost::shared_ptr<BC> create(const string & name)
        {
            assert(m_.find( name ) != m_.end());
            // name wurde nochnicht registriert
            // kommt auf dein programm an ob hier ein assert reicht 
            return boost::shared_ptr<BC>( m_[name].clone() );
        }
    private:
        std::map<string, boost::shared_ptr<BC> > m_;
    };
    
    int main()
    {
        Factor f;
        f.reg(boost::shared_ptr<BC>( new CCa ), "a" );
        f.reg(boost::shared_ptr<BC>( new CCb ), "b" );
        f.reg(boost::shared_ptr<BC>( new CCc ), "c" );
    
        boost::shared_ptr<BC> p = f.create( "a" );
    

    ahja für boost::shared_pre muss du dir boost von www.boost.org installieren

    [ Dieser Beitrag wurde am 10.05.2003 um 10:49 Uhr von Dimah editiert. ]



  • Original erstellt von Peanut:
    **
    Kann man nicht alle aufrufe von Memberfunktionen transparent weiterleitenleiten**

    kannst du schon, indem du einfach alle mathoden, die alle unterklassen haben sollen, in der basisklasse definierst. eine etwas elegantere lösung:

    #include <iostream>
    using namespace std;
    class BaseClass {
        public:
            virtual void aktion1() = 0; // rein virtuelle klasse
            virtual void aktion2();
            virtual void aktion3();
    };
    
    class Container1 : public BaseClass {
        public:
            virtual void aktion1() { cout << "Aufgerufen: Containter1->Aktion1" << endl; }
            virtual void aktion2() { cout << "Aufgerufen: Containter1->Aktion2" << endl; }
            virtual void aktion3() { cout << "Aufgerufen: Containter1->Aktion3" << endl; }
    };
    
    class Container2 : public BaseClass {
        public:
            virtual void aktion1() { cout << "Aufgerufen: Containter2->Aktion1" << endl; }
            virtual void aktion2() { cout << "Aufgerufen: Containter2->Aktion2" << endl; }
            virtual void aktion3() { cout << "Aufgerufen: Containter2->Aktion3" << endl; }
    };
    
    class Container3 : public BaseClass 
    {
        public:
            virtual void aktion1() { cout << "Aufgerufen: Containter3->Aktion1" << endl; }
            virtual void aktion2() { cout << "Aufgerufen: Containter3->Aktion2" << endl; }
            virtual void aktion3() { cout << "Aufgerufen: Containter3->Aktion3" << endl; }
    };
    
    class Container4 : public BaseClass 
    {
        public:
            virtual void aktion1() { cout << "Aufgerufen: Standard-Containter->Aktion1" << endl; }
            virtual void aktion2() { cout << "Aufgerufen: Standard-Containter->Aktion2" << endl; }
            virtual void aktion3() { cout << "Aufgerufen: Standard-Containter->Aktion3" << endl; }
    };
    
    class Fabrik {
        private:
            BaseClass *container;
        public:
            Fabrik() { container = new Container4; }
            Fabrik(int type)
            {  
                if (type == 1) container = new Container1;
                else if (type == 2) container = new Container2;
                else if (type == 3) container = new Container3;
                else container = new Container4;
            } 
            ~Fabrik() { delete container; }
            void aktion1() { if (container) container->aktion1(); }
            void aktion2() { if (container) container->aktion2(); }
            void aktion3() { if (container) container->aktion3(); }
    };
    
    int main ()
    {
        Fabrik f1(1), f2(2), f3(3), f4;
        f1.aktion1();
        f2.aktion2();
        f3.aktion3();
        f4.aktion1();
    }
    
    Output:
    > Aufgerufen Container1->Aktion1
    > Aufgerufen Container2->Aktion2
    > Aufgerufen Container3->Aktion3
    > Aufgerufen Standard-Container->Aktion1
    

    So hast du bequem alle aufrufe in der fabrik drin.

    [ Dieser Beitrag wurde am 10.05.2003 um 11:19 Uhr von Korbinian editiert. ]



  • Korbinian dein sytem ist etwas erweiterungs feindlich

    class Fabrik {
        private:
            BaseClass *container;
        public:
            Fabrik() { container = new Container4; }
            Fabrik(int type)
            {  
                if (type == 1) container = new Container1;
                else if (type == 2) container = new Container2;
                else if (type == 3) container = new Container3;
                else container = new Container4;
            } 
            ~Fabrik() { delete container; }
    
            BaseClass * operator-> ()
            {
                // das if ist unnötig da duch die ctoren sichergestelt ist das container auf was zeigt
                return container;
            }
    };
    


  • hm, mit dieser lösung wird aber folgendes schwierig:

    Fabrik *f1 = new Fabrik(1);
    f1->will_normale_methode_von_fabrik();
    

    was machste dann?



  • das was man erwartet, dann muss du so machen

    Fabrik *f1 = new Fabrik(1);
    (*f1)->will_normale_methode_von_fabrik();
    
    // oder
    Fabrik & f1 = *new Fabrik(1);
    f1->will_normale_methode_von_fabrik();
    


  • ah 🙂 darauf wär ich jetz so schnell nicht gekommen

    btw: hab was im mod-forum gepostet, falls noch nicht gesehn


Anmelden zum Antworten