c++ - 使用类似策略模式的文件解析器 - 如何获得结果?

标签 c++ c++11 strategy-pattern nmea

假设我想制作一个文件解析器,它使用类似策略的模式来允许使用不同的特定解析器,这些解析器将完成所有艰苦的工作,然后返回它们之间可能有所不同的结果。

例如,文件的每一行都包含 A、B、C、D 和 E,而我只想获取 A、C 和 E,因此我创建了一个特定的解析器来仅提取它们。

我还应该注意,我正在处理 NMEA 格式,每个解析器将处理文件中的不同语句(行)。

class FileParser
{
std::string file_path;
public:
    FileParser(std::string file_path, ??? parser);

    void parseFile() {
        // ...
        // for each line:
            parser.parseStatement(line);
        // end for
        // ...
    }

    ??? getResults() {
        return parser.getResults();
    }
};

class Parser
{
public:
    virtual void parseLine(std::string line);
    ??? getResults();
}

class SpecificParser : public Parser
{
    void parseLine(std::string line);
    SpecificFormat getResults();
}

我的问题是 - 如何正确编写这样的代码? 我的第一个想法是模板,但我还不知道如何使用它们,所以第二个想法是:

FileParser otherFunction() {
    ExampleParser ep();
    FileParser fp("example.txt", &ep);
    return fp;
}

void function() {
    FileParser fp = otherFunction(); // countains reference to deleted instance of ExampleParser
}

...但它也有问题(我故意展示了一个边缘情况)。

构建该代码的正确方法是什么?

示例用例(如下要求)

auto parser1 = FileParser<SpecificParserType1>(file_name);
parser1.parseFile();
auto parser1.getResults(); // returns instance of specific type 1, e.g. std::vector<Type1>

auto parser2 = FileParser<SpecificParserType2>(file_name);
parser2.parseFile();
auto parser2.getResults(); // returns instance of specific type 2, e.g. std::vector<Type2>

主要目标是能够采用不同的策略从文件中获取数据。

最佳答案

从我的角度来看,您在这里使用策略模式的想法是错误的,因为:

您想要创建一个始终具有几乎相同签名的类层次结构,这已经显示了您的问题:存在设计问题,因为您的具体策略方法不是> 策略的变体,因为它具有不同的返回类型。

如果这样的事情可以通过像指向任何东西的指针这样的黑客来实现,那么你就会遇到下一个问题。因此,让我们定义任何东西都可以简化为数据对象

您的具体文件解析器读取策略方法提供了大量不同的数据对象类型,这些类型必须在程序中的某个位置进行描述才能处理此类数据。提示:您的数据对象将具有哪种类型的接口(interface)?也许您想读取一些 int 值,但也想读取 std::string 对象和容器类。这些类型有通用接口(interface)吗?

如果您的数据类型没有这样一个通用接口(interface),您只需打破一般的 OOP 设计规则:永远不要从外部查看类/对象内部的细节。您的解决方法可能是这样的:

switch ( dataobject[n].getType() ) 
{
    case INT:
        ...;
    case STRING:
        ...;

    ... and all the objects you have defined yourself!
}

您现在编写如下代码:

auto parser1.getResults();

您的结果必须始终相同。 auto 并不意味着它可以在运行时改变它的类型。所以这不是这里的解决方案。

下一个问题: 您的程序代码似乎对文件的内容做出了一些假设。策略模式的用户必须知道对象如何以具体顺序存储在文件中。更好的方法是对象包含一些内容,并且解析器可以处理它。但这里的策略模式并不正确。

我的提示: 如果您的设计独立于任何设计模式,导致定义一个类层次结构,其中包含一些必须具有不同返回类型的虚函数(这是不可能的),那么您的设计就被破坏了!

关于c++ - 使用类似策略模式的文件解析器 - 如何获得结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31558686/

相关文章:

java - 策略设计模式(带参数方法)- JAVA

c++ - C++读取注册表项值的数据

c++ - 如何将返回 C++ 自定义类的函数与 Cython 连接?

c++ - 为什么带有自定义删除器的 unique_ptr 不适用于 nullptr,而 shared_ptr 可以?

c++ - 通过引用问题

.net - 如何将策略模式与依赖注入(inject)(autofac)一起使用

c++ - 使用 C++ 模板切换策略/算法

c++ - 为什么某些设备不使用 SetupDiGetDeviceInterfaceDetail() 进行枚举?

c++构造函数将引用传递给基类对象

c++ - 编译器如何处理变长数组