Hier geht es um die Erzeugung von Objekten in Konstruktoren. Klasse WantToTest erzeugt im Konstruktor ein Wrapperobjekt der Klassen A und B. Klasse A wird mit 20 initialisiert, was 20 Datenbank-Verbindungen bedeutet.
Hier das Szenario in C++
#include <iostream>
#include <tr1/memory>
class A
{
public:
A(int n)
: m_NumberOfDBConnections(n)
{}
A()
: m_NumberOfDBConnections(0)
{}
int m_NumberOfDBConnections;
};
class B
{
public:
B(int i)
: i(i)
{}
int i;
};
typedef std::tr1::shared_ptr<A> PtrA;
typedef std::tr1::shared_ptr<B> PtrB;
class AB
{
private:
PtrA m_A;
PtrB m_B;
public:
AB(PtrA a, PtrB b)
: m_A(a), m_B(b)
{
}
AB ()
{}
A* GetA()
{
return m_A.get();
}
};
typedef std::tr1::shared_ptr<AB> PtrAB;
class WantToTest
{
public:
WantToTest()
{
PtrA a (new A(10));
PtrB b (new B(20));
PtrAB ab ( new AB(a,b));
m_AB = ab;
}
private:
PtrAB m_AB;
};
Da in Tests keine Datenbank-Kommunikation vorkommen soll, wollen wir dies gerne verhindern. Wir wollen wie bei Extract Method and Overwrite Call, den Kontruktoraufruf extrahieren und überschreiben:
class WantToTestCreationExtracted
{
public:
WantToTestCreationExtracted()
{
m_AB = CreateAB();
}
PtrAB CreateAB()
{
PtrA a (new A(10));
PtrB b (new B(20));
PtrAB ab ( new AB(a,b));
return ab;
}
AB* GetAB()
{
return m_AB.get();
}
private:
PtrAB m_AB;
};
class CanTest: public WantToTestCreationExtracted
{
PtrAB CreateAB()
{
PtrA a (new A(0));
PtrB b (new B(0));
PtrAB ab ( new AB(a,b));
return ab;
}
};
Folgender Test spuckt aber 10 aus:
int main()
{
CanTest t;
A* a = t.GetAB()->GetA();
std::cout << (a->m_NumberOfDBConnections);
return 0;
}
Das lässt sich damit erklären, dass C++ zum Zeitpunkt des Konstruktoraufrufs der Basisklasse keine abgeleitete Klasse kennt. So lautet denn Scott Meyers Tip 9 in Effektiv C++ programmieren auch, niemals während der Konstruktion oder der Zerstörung virtuelle Funktionen aufzurufen, da diese Funktionen nicht über die Basisklasse hinauskommen.
0 Responses to “Fabrik-Methode extrahieren und überschreiben”