封装这种功能的正确方法是什么?

时间:2015-05-05 16:27:45

标签: encapsulation

例如,我有一个基本上以这种方式工作的功能:

function myfunc(data,type_of_analysis){
    if type_of_analysis is "Smith-Jones Method" 
          return smith_jones(data)
    else if type_of_analysis is "Pineapple-Mango Method"
          return pineapple_mango(data)
}

名称由当然组成,并且假设有比这更多类型的分析。重构myfunc()的正确方法是什么?是否有更好/更标准的方式让人们通过参数来确定他们想要执行什么样的分析?或者这是用户必须在文档中查找的东西吗?

1 个答案:

答案 0 :(得分:1)

这是C ++中的一个示例,它使用枚举值和函数对象之间的映射来提供类型安全且灵活的调度框架:

//dummy analysis functions
void smithJonesAnalysis (int data){cout << "Smith";}
void pineappleMangoAnalysis (int data){cout << "Pineapple";}

class Analyzer
{
    //different analysis methods
    enum class AnalysisMethod {SmithJones, PineappleMango};
    //a map from analysis method to a function object
    std::map<AnalysisMethod, std::function<void(int)>> m_analysis_map;

    AnalysisMethod stringToMethod (std::string method)
    {
        //some basic string canonicalisation
        std::transform(method.begin(), method.end(), method.begin(), ::tolower);
        if (method == "smith-jones method")
            return AnalysisMethod::SmithJones;
        if (method == "pineapple-mango method")
            return AnalysisMethod::PineappleMango;

        throw std::runtime_error("Invalid analysis method");
    }
public:
    Analyzer()
    {
        //register all the different functions here
        m_analysis_map[AnalysisMethod::SmithJones] = smithJonesAnalysis;
        m_analysis_map[AnalysisMethod::PineappleMango] = pineappleMangoAnalysis;
    }

    //dispatcher function
    void operator() (std::string method, int data)
    {
        AnalysisMethod am = stringToMethod(method);
        m_analysis_map[am](data);
    }
};

它的用法如下:

Analyzer a;
a("Smith-Jones Method", 0);
a("Pineapple-Mango Method", 0);

Demo

与简单的switch语句相比,这有许多优点:

  • 添加/删除分析方法更容易
  • 更改方法接受的数据类型
  • 更容易
  • 您可以针对不同的区域设置不同的Analyzer,模板化和专业化,并且您需要更改的只是注册方法。
  • 您可以在运行时以非常清晰的方式启用/禁用分析方法