在C++中填充地图容器时的多晶型设计

Polymorph design when filling a map container in C++

本文关键字:晶型 C++ 填充 地图      更新时间:2023-10-16

我不擅长OOP设计,但我需要向潜在雇主展示我的知识。情况如下:

我有一个包含键值类型参数的文件,称为 parameters.txt 。我有一个map <string, CommonParamValue>作为容器。我需要用元素填充它,使用带有参数的文件。键始终是一个std::string参数,CommonParamValue可以用intdoublestring和标准函数调用来表示。为了实现这一点,CommonParamValue是一个带有虚拟方法的基类。它有孩子 - StringParamValueDoubleParamValueCurTimeParamValue。基类和每个子类都有一个返回内部数据的字符串表示形式的方法virtual string GetValue(); virtual void SetValue(string)设置值。

问题是如何使用多态性在运行时用适当的数据填充容器map <string, CommonParamValue>现在我有这样的情况:

参数.txt

*user_name=Jane
*order_number=1325
current_date=

填充地图的例程

ifstream in(fileParamsPath);
    if (! in)
    {
        cout << "Cannot open file with parameters, program is terminating." << endl;
        cin.get();
        exit(-1);
    }
    string key = "", value = "";
    while(in)
    {
        getline(in, key, '=');
        getline(in, value, 'n');
        // put key and value into the container
        // right here we need to analyze the data type and choose appropriate container.
        // CommonParamValue *paramValue = new DoubleParamValue(); or
        // CommonParamValue *paramValue = new CurTimeParamValue(); or
        // CommonParamValue *paramValue = new StringParamValue();
        paramValue->SetValue(value);
        params.insert(make_pair(key, *paramValue)); // params is a map <string, CommonParamValue>
        delete paramValue;
    }
    in.close();

有一个想法是将值参数的类型保留在文件parameters.txt中,并在填充时对其进行分析map <string, CommonParamValue>

参数.txt

*user_name=Jane
string
*order_number=1325
int
current_date=
function

并通过以下方式修改填充map <string, CommonParamValue>例程:

string key = "", value = "", type = "";
    while(in)
    {
        getline(in, key, '=');
        getline(in, value, 'n');
        getline(in, type, 'n');
        in.get(); // got the dividing empty string
        // put key and value into the container
        // right here we need to analyze the data type and choose appropriate container.
        if(type == "int")
        {
            CommonParamValue *paramValue = new IntParamValue();
        }
        else if(type == "function")
        {
            CommonParamValue *paramValue = new CurTimeParamValue();
        }
        else if(type == "string")
        {
            CommonParamValue *paramValue = new StringParamValue();
        }
        else
        {
            // error
            exit(1);
        }
        paramValue->SetValue(value);
        params.insert(make_pair(key, *paramValue)); // params is a map <string, CommonParamValue>
        delete paramValue;
    }

这是一个好决定还是坏决定?也许我的潜在雇主希望我以其他方式实施它,但我只有这个决定。对于初级C++程序员来说,还有更好的方法吗?

最经典的设计是工厂方法设计。

CommonParamValue* createParamValue( const std::string &value );

createParamValue 方法负责创建适当的派生ParamValue并将其作为CommonParamValue返回。

通过使用值字符串推断类型,可以避免将"type"的其他字符串泵入parameters.txt createParamValue 内部。正则表达式听起来像是intdoubleCurTime最优雅的。Boost 正则表达式是一个示例库,可让您在 c++ 中执行此操作。但是,当然,如果您正在寻找快速解决方案,那么编写自己的30行决策树对于这些简单的语法来说应该不是问题。

客户端代码中的 if 语句对我来说看起来有点不稳定。可以尝试工厂课程吗?

具有基类 IParamValue

IntParamValue : public IParamValue { }
static IParamValue * Create(string selection);
IParamValue * IParamValue::Create(string selection)
{
    if (selection == "int") return new IntParamValue();
    ...
}

客户端代码:

IParamValue* param = IParamValue::Create ("something");