c++ - 通过使用字符串调用新构造函数来创建新对象

标签 c++ design-patterns factory-pattern

我最近参加了一次工作面试,面试官给了我一个建模问题,涉及将不同的形状序列化到一个文件中。

任务是通过首先定义一个名为 Shape 的抽象类来实现圆形或矩形等形状,然后通过从基类 (Shape) 继承来实现各种形状(圆形、矩形......)。

每个形状的两个抽象方法是:read_to_file(应该从文件中读取形状)和 write_to_file 应该将形状写入文件。

所有这些都是通过在继承的形状中实现该虚函数来完成的(例如:对于圆,我写的是半径,对于正方形,我保存了正方形的边....)。

class Shape {
public:
    string Shape_type;

    virtual void write_into_file()=0;

    virtual void read_into_files()=0;

    Shape() {
    }
    virtual ~Shape() {
    }};
class Square: public Shape {
public:
    int size;
    Square(int size) {
        this->size = size;
    }
    void write_into_file() {
        //write this Square into a file
    }
    void read_into_files() {
        //read this Square into a file
    }
};

这样做是为了看看我是否了解多态性。

但是,然后我被要求实现两个函数,它们采用 *shape vector 并将其写入/读取到文件中。

写作部分很简单,大概是这样的:

for (Shape sh : Shapes) {
    s.write_into_file();
}

至于阅读部分,我考虑过阅读文本中的第一个单词(我将可序列化文件实现为具有以下行的文本文件:Shape_type: Circle, Radius: 12; Shape_type:Square... .,所以第一个字表示形状类型)。并将其保存为一个字符串,例如:

string shape_type;
shape_type="Circle";

然后我需要创建该特定形状的新实例,我想到了类似大开关的东西

<pre><code>
switch(shape_type):
{
case Circle: return new circle;
case Square: return new square
......
}
</pre></code>

然后面试官跟我说这个实现有问题 我认为这是一个事实,即我们将在未来添加的每个新形状我们也应该更新那个大开关。他试图引导我进入设计模式,我告诉他也许工厂设计模式会有所帮助,但我找不到摆脱该开关的方法。即使我将开关从函数移动到 FactoryClass 我仍然必须使用开关来检查形状的类型(根据我从文本文件中获得的字符串内容) .

我从文件中读取了一个字符串,表示形状的当前类型。我想做类似的事情:

string shape_type;
shape_type="Circle";
Shape s = new shape_type; //which will be like: Shape s = new Circle

但我不能用 c++ 做。

知道我应该做什么吗?

最佳答案

在您的工厂中,您可以映射 std::stringfunction<Shape*()> .在启动时,您将向工厂注册工厂方法:

shapeFactory.add("circle", []{new Circle;});
shapeFactory.add("square", []{new Square;});
shapeFactory.add("triangle", []{new Triangle;});

在反序列化代码中,您读取类型的名称并从工厂获取其工厂方法:

std::string className = // read string from serialization stream
auto factory = shapeFactory.get(className);
Shape *shape = factory();

您现在已获得指向具体形状实例的指针,可用于反序列化对象。

编辑:根据要求添加了更多代码:

class ShapeFactory
{
private:
  std::map<std::string, std::function<Shape*()> > m_Functions;

public:

  void add(const std::string &name, std::function<Share*()> creator)
  {
    m_Functions.insert(name, creator)
  }

  std::function<Shape*()> get(const std::string &name) const
  {
    return m_Functions.at(name);
  }
};

注意:我省略了错误检查。

关于c++ - 通过使用字符串调用新构造函数来创建新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20615212/

相关文章:

ruby 模式问题

c++ - cout << 1 && 0; 的输出

java - 如何解决先有鸡还是先有蛋的问题?

c# - 服务器和客户端之间实现心跳的模式

c++ - 在C++中使用静态方法实现工厂模式

validation - 工厂构造函数中的参数验证?

java - 使用 Spring 实现工厂方法

c++ - 给奶牛的款待——自下而上的动态规划

C++ 命令行调试参数

c++ - 读取文件所需的 std::getline 的替代方法