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 polymorphielies 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 mitvoid 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