What is your opinion about my code ?
#ifndef PROTOTYPE_H
#define PROTOTYPE_H
#include <map>
// =============================================
class prototype
{
public:
prototype();
~prototype();
virtual prototype* clone(prototype* ) = 0;
virtual void initialize(const bool&, const int&,
const std::string& ) = 0;
virtual bool getHasTurbo() const = 0 ;
virtual int getCapacity() const = 0;
virtual const std::string& getCategory() const = 0;
virtual void display() const = 0;
};
// =============================================
#endif
#include "Prototype.h"
// =============================================
prototype::prototype()
{
}
// =============================================
prototype::~prototype()
{
}
#ifndef VEHICLE_PROTOTYPE_H
#define VEHICLE_PROTOTYPE_H
#include "Prototype.h"
#include <string>
// ==============================================
class vehiclePrototype : public prototype
{
public:
vehiclePrototype();
vehiclePrototype(const bool&, const int&,
const std::string&);
vehiclePrototype(prototype* );
~vehiclePrototype();
prototype* clone(prototype* );
void initialize(const bool&, const int&,
const std::string& );
bool getHasTurbo() const;
int getCapacity() const;
const std::string& getCategory() const;
void display() const ;
private:
int capacity;
bool hasTurbo;
std::string category;
};
// =============================================
#endif
#include "VehiclePrototype.h"
#include <iostream>
// =============================================
vehiclePrototype::vehiclePrototype()
: capacity(0), hasTurbo(bool() ),
category(std::string() )
{
}
// =============================================
vehiclePrototype::vehiclePrototype(const bool& userHasTurbo,
const int& userCapacity,
const std::string& userCategory)
{
hasTurbo = userHasTurbo;
capacity = userCapacity;
category = userCategory;
}
// ============================================
vehiclePrototype::vehiclePrototype(prototype* rhs)
{
hasTurbo = rhs->getHasTurbo();
capacity = rhs->getCapacity();
category = rhs->getCategory();
}
// ============================================
vehiclePrototype::~vehiclePrototype()
{
}
// =============================================
prototype* vehiclePrototype::clone(prototype* myPrototype)
{
return new vehiclePrototype(myPrototype);
}
// =============================================
void vehiclePrototype::initialize(const bool& userHasTurbo,
const int& userCapacity,
const std::string& userCategory)
{
hasTurbo = userHasTurbo;
capacity = userCapacity;
category.assign(userCategory);
}
// =============================================
bool vehiclePrototype::getHasTurbo() const
{
return hasTurbo;
}
// =============================================
int vehiclePrototype::getCapacity() const
{
return capacity;
}
// =============================================
const std::string& vehiclePrototype::getCategory() const
{
return category;
}
// =============================================
void vehiclePrototype::display() const
{
std::cout << std::boolalpha
<< "Car Specification\n"
<< "Vehicle Category Type : " << getCategory() << "\n"
<< "Vehicle Capacity : " << getCapacity() << "\n"
<< "Vehicle Turbo : " << getHasTurbo() << "\n";
}
// =============================================
#ifndef PROTOTYPE_MANAGER_H
#define PROTOTYPE_MANAGER_H
#include <map>
#include <vector>
class prototype;
// =============================================
class prototypeManager
{
public:
typedef std::map<int, prototype* > prototypeMap;
typedef std::map<int, prototype* >::iterator prototypeMapIte;
typedef std::vector<prototype*> prototypeVec;
public:
prototypeManager();
~prototypeManager();
prototype* createVehicle(int, const bool&,
const int&, const std::string& );
void populateVehicle();
// To create a specific instance of a class
// without coding the class
void registerVehicle( const bool&,
const int&, const std::string&);
void registerVehicle(const int&, const bool&,
const int&, const std::string&);
void unRegisterVehicle(int);
private:
static int vehicleType;
prototypeMap registry;
// Static Product
// Empty Prototype
prototype* obj;
prototype* sedan, *superCar, *f1Car;
// Dynamic Product
prototypeVec cont;
};
// =============================================
#endif
#include "PrototypeManager.h"
#include "VehiclePrototype.h"
#include <iostream>
// =============================================
int prototypeManager::vehicleType = 1;
// =============================================
prototypeManager::prototypeManager()
: registry(prototypeMap()), obj(new vehiclePrototype),
sedan(new vehiclePrototype(false, 1600, "B Class") ),
superCar(new vehiclePrototype(true, 3000, "D Class") ),
f1Car(new vehiclePrototype(true, 6000, "F Class") ),
cont(prototypeVec() )
{
populateVehicle();
}
// =============================================
prototypeManager::~prototypeManager()
{
delete obj;
delete sedan;
delete superCar;
delete f1Car;
obj = 0;
sedan = 0;
superCar = 0;
f1Car = 0;
for (size_t loop = 0;loop<cont.size();++loop)
{
delete cont[loop];
cont[loop] = 0;
}
}
// =============================================
prototype* prototypeManager::createVehicle(
int uservehicleType,
const bool& userHasTurbo,
const int& userCapacity,
const std::string& userCategory)
{
prototypeMapIte myIte = registry.find(uservehicleType);
prototype* instance = 0;
if (myIte == registry.end() )
{
// Register Vehicle
registerVehicle(uservehicleType, userHasTurbo,
userCapacity, userCategory);
myIte = registry.find(uservehicleType);
prototype* temp = myIte->second;
instance = obj->clone(temp);
instance->initialize(userHasTurbo, userCapacity,
userCategory);
}
else
{
prototype* temp = myIte->second;
instance = obj->clone(temp);
instance->initialize(userHasTurbo, userCapacity,
userCategory);
}
std::cout << "\nClone Vehicle\n";
return instance;
}
// =============================================
void prototypeManager::populateVehicle()
{
registry.insert(prototypeMap::value_type(vehicleType, sedan) );
++vehicleType;
registry.insert(prototypeMap::value_type(vehicleType, superCar) );
++vehicleType;
registry.insert(prototypeMap::value_type(vehicleType, f1Car) );
++vehicleType;
}
// =============================================
void prototypeManager::registerVehicle(
const bool& userHasTurbo,
const int& userCapacity,
const std::string& userCategory)
{
prototype* temp = new vehiclePrototype(userHasTurbo,
userCapacity, userCategory);
cont.push_back(temp);
registry.insert(prototypeMap::value_type(vehicleType, temp) );
++vehicleType;
std::cout << "\nRegister new Vehicle Type "
<<vehicleType << "\n";
}
// =============================================
void prototypeManager::registerVehicle(const int& userVehicleTpye,
const bool& userHasTurbo,
const int& userCapacity,
const std::string& userCategory)
{
prototype* temp = new vehiclePrototype(userHasTurbo,
userCapacity, userCategory);
cont.push_back(temp);
registry.insert(prototypeMap::value_type(userVehicleTpye, temp) );
std::cout << "\nRegister new Vehicle Type "
<<userVehicleTpye << "\n";
}
// =============================================
void prototypeManager::unRegisterVehicle(int vehicleType)
{
prototype* removePrototype = registry.find(vehicleType)->second;
registry.erase(vehicleType);
std::cout << "\nUnRegister Vehicle Type "
<< vehicleType << "\n";
}
// =============================================
#include <iostream>
using namespace std;
#include "Prototype.h"
#include "VehiclePrototype.h"
#include "PrototypeManager.h"
// =============================================
// =============================================
// =============================================
int main()
{
prototypeManager obj;
prototype* myCar;
myCar = obj.createVehicle(1, false, 1300, "B Class");
myCar->display();
myCar = obj.createVehicle(2, true, 3200, "D Class");
myCar->display();
myCar = obj.createVehicle(5, false, 2500, "E Class");
myCar->display();
obj.unRegisterVehicle(1);
myCar = obj.createVehicle(1, false, 1600, "B Class");
myCar->display();
return 0;
}
How to dynamic loading in C++ ?
I read the Gof book and i don;t understand the third consequences (pg 120) specifying new object by varying structure. Please explain.
Thanks.
//subjective
It can be improved in many places.
Destructor should be virtual
Omitted argument names. Bad idea. Parameter names automatically document your code and their names are supposed to explain their meaning. Also, they are used in autocomplete/intellisense features, so removing them is really a bad taste.
Using something like “typedef std::string Str” will make your code shorter
Doesn’t make sense. If you wanted to make copy of current object, you should have used no parameter and this should have been const. If you wanted to turn this object into copy of object given in argument (really bad idea – they could be incompatible, in which case clone should be called assign), you should have used const argument and function should have been void (or it could return Reference). Or if you wanted generic routine for copying objects, it should have been static.
bool and int are “small” types so using const reference them is pointless.
There are no fields in base class, so you don’t need a constructor
Why? Just provide default values, you don’t need to give bool() or std::string(). Or don’t provide any constructor at all. std::string will be automatically initialized to empty string. Giving it another std::string is waste of characters in your file.
This can be done using :hasTurbo(userHasTurbo). It doesn’t make sense to call assignment unless you have to calculate value during constructor.
It makes sense to use different name format for classes, methods and variables. In my code all class names start with uppercase letter (class Prototype). variables and methods start with lowercase letter (void Prototype::doSomething).This allows to create instance of class using same name (i.e. Prototype prototype). I think Qt 4 uses somewhat similar scheme.
Code like this rasies questions like “who is going to delete all prototype pointer”. It is better to use smart pointers instead of prototype*.
You don’t really need that you could use prototypeMap::iterator.
And this is why you need smart pointers – you could just call clear() if you used smart pointers.. Also you don’t need to set objects to zero. you’re in destructor, so nobody will try to access them anymore anyway.
It should be “instance = obj->clone()” or “instance = Prototype::clone(obj)”. Otherwise the logic if ambiguous – you use one object to make copy of another object of same type. Things like this introduce subtle deadly ninja bugs.
prototypeMap has size() parameters that could be used instead of vehicleType – in THIS case and if map was initialized just once.
Also the proper use would be prototypeMap[vehicleType] = sedan.
I believe that proper way would be to use std::endl instead of \n. Unix and Windows use different line endings.
Could cause memory leak if prototype used in map was created outside of class.
You need Prototype pattern. Every class derived from base Prototype class should have method clone() const; (with NO arguments) which will return copy of current class. Make a map, fill it with empty objects corresponding for each id. If object found in map, call clone, return new copy, and call virtual load() method. This way you’ll get “dynamic loading”.