For example, I want to convert json from server to generic object: Shape, as follow:
{
"type":"Circle",
"radius":"3",
},
{
"type":"Rectangle",
"width":"5",
"height":"6",
},
using c++ and rapidJson as example here:
/*main.cpp*/
void getResponse(const char* responseText){
Document d;
d.parse(responseText);
for(SizeType i = 0; i < a.Size(); i++){
if(d[i]["type"]="Circle"){
this->shapeVector.push_back(new Circle(d[i]));
}else if(...){
}
}
for(Shape* s : this->shapeVector){
printf("%f\n",s->getArea());
}
}
I know it is very bad to use
if(d[i]["type"]="Circle"){
}else if(...){
}
to convert a value to type here, so I try modify it to use registry pattern:
Shape:
/*Shape.h*/
#include <map>
class Shape{
public:
virtual Shape* jsonToObj(const char* str)=0;
virtual float getArea()=0;
static std::map<const char*,Shape*> objMap;
};
/*Shape.cpp*/
#include "Shape.h"
std::map<const char*,Shape*> Shape::objMap;
Circle:
/*Circle.h*/
#include "Shape.h"
class Circle : public Shape{
public:
float radius;
virtual Shape* jsonToObj(Value value){
Circle* s=new Circle();
s->radius=value["radius"];
return s;
}
virtual float getArea(){
return 3.14*this->radius*this->radius;
}
static long _;
};
/*Circle.cpp*/
#include "Circle.h"
long Circle::_=[](){ Shape::objMap["Circle"]=new Circle();return 0;}();
main:
/*main.cpp*/
void getResponse(const char* responseText){
Document d;
d.parse(responseText);
for(SizeType i = 0; i < a.Size(); i++){
this->shapeVector.push_back(Shape::objMap[d[i][name]].jsonToObj(d[i]));
}
for(Shape* s : this->shapeVector){
printf("%f\n",s->getArea());
}
}
which I convert value "type" to corresponding object type by asking Shape::objMap. When I need to add a type ,for example:Rectangle, I can add Rectangle.h and Rectangle.cpp without modify the if-else in main.cpp:
Rectangle:
/*Rectangle.h*/
#include "Shape.h"
class Rectangle : public Shape{
public:
float width;
float height;
virtual Shape* jsonToObj(Value value){
Rectangle* s=new Rectangle();
s->width=value["width"];
s->height=value["height"];
return s;
}
virtual float getArea(){
return this->width*this->height;
}
static long _;
};
/*Rectangle.cpp*/
#include "Rectangle.h"
long Rectangle::_=[](){ Shape::objMap["Rectangle"]=new Rectangle();return 0;}();
/*main.cpp*/
void getResponse(const char* responseText){
Document d;
d.parse(responseText);
for(SizeType i = 0; i < a.Size(); i++){
this->shapeVector.push_back(Shape::objMap[d[i][name]].jsonToObj(d[i]));
}
for(Shape* s : this->shapeVector){
printf("%f\n",s->getArea());
}
}
But according to Why is Global State so Evil?, I should not use global state, which
Shape::objMap
is a global map. My question is, is it a reasonable case to use global state? If-else and global map, which is more "evil" here?