I have just started reading the GO4 book to learn the OOD concepts. In order to practice the Prototype pattern, I implemented a small example (the idea for colored shapes was taken from "refactoring.guru"). Following is my code with some questions beneath.
Prototype definition:
enum class Shape
{
Circle,
Rectangle,
};
class ColoredShapePrototype
{
protected:
std::string color_;
public:
ColoredShapePrototype() {}
ColoredShapePrototype(std::string color) : color_(color) {}
virtual ~ColoredShapePrototype() {}
virtual ColoredShapePrototype* Clone() const = 0;
virtual void ShapeDetails() { std::cout << "Color: " << color_ << "\n"; }
virtual void UpdateColor(int color) { color_ = color; }
};
class ColoredCirclePrototype : public ColoredShapePrototype
{
private:
int radius_;
public:
ColoredCirclePrototype(std::string color, int raduis) : ColoredShapePrototype(color), radius_(raduis) {}
ColoredShapePrototype* Clone() const override { return new ColoredCirclePrototype(*this); }
void ShapeDetails() { ColoredShapePrototype::ShapeDetails(); std::cout << "Radius: " << radius_ << "\n"; }
};
class ColoredRectanglePrototype : public ColoredShapePrototype
{
private:
int height_;
int width_;
public:
ColoredRectanglePrototype(std::string color, int height, int width) : ColoredShapePrototype(color), height_(height), width_(width) {}
ColoredShapePrototype* Clone() const override { return new ColoredRectanglePrototype(*this); }
void ShapeDetails() { ColoredShapePrototype::ShapeDetails(); std::cout << "Height: " << height_ << "\nWidth:" << width_ << "\n"; }
};
class ShapesPrototypeFactory
{
private:
std::unordered_map<Shape, ColoredShapePrototype*> prototypes_;
public:
ShapesPrototypeFactory() {
prototypes_[Shape::Circle] = new ColoredCirclePrototype("White", 5);
prototypes_[Shape::Rectangle] = new ColoredRectanglePrototype("White", 2, 3);
}
~ShapesPrototypeFactory() {
delete prototypes_[Shape::Circle];
delete prototypes_[Shape::Rectangle];
}
ColoredShapePrototype* CreatePrototype(Shape shape) { return prototypes_[shape]->Clone(); }
};
Usage in main:
ShapesPrototypeFactory prototype_factory;
ColoredShapePrototype* circ = prototype_factory.CreatePrototype(Shape::Circle);
circ->ShapeDetails();
ColoredShapePrototype* rect = prototype_factory.CreatePrototype(Shape::Rectangle);
rect->ShapeDetails();
delete circ;
delete rect;
Questions:
-
Interfaces in general - pure virtual functions and other variables are declared, and derived classes should implement those. Suppose I want to add a specific capability (with unique data member and member function) to the derived - Does it contradict the interface idea? (Because, if I have a pointer from base to derived, this pointer will not recognize the specific method...). If it is OK, Is there a way to execute a derived function through the interface(who doesnt have this function..)?
-
while debugging and watching circ variable, I can see the variable in the memory window, and I see "white" color, but I cant find the radius there. Is there a way i can see specific data member address in the memory? (I have tried circ->radius_ etc. none was working..)
-
I have seen that most implementations are using "unique_ptr". I know its basic usage, but how critical it is? and why not use it all the times rather than a regular pointer actually? and where are the places I should use it in the prototype pattern?
-
Implementing Copy Constructor in case of non-stack variables (shallow/deep copying) for the clone operation - Is a CCtor in the base class is sufficient or the derived is required as well?
-
Code review - better syntax/design/ideas/improvements?
Thanks in advance, I will highly appreciate your help!
Aucun commentaire:
Enregistrer un commentaire