【问题标题】:Elegant numerical->letter academic grade mapping优雅的数字->字母学术成绩映射
【发布时间】:2014-05-11 09:26:49
【问题描述】:

这是一个简单的例子,我想开始揭露这个问题。

假设您有一堆数字,范围从 0 到 10,并且您想将它们映射到字母等级(A、B、C、D、F)。

可以编写一系列if 语句来测试相应字母范围内的给定数字并返回正确的字母。

问题是:什么模式可以用来使它更健壮,也许更解耦?例如,如果我有 10 个而不是 5 个数字范围,我将不得不编辑这个整体方法来添加其他 5 个案例。我也不能保证我的范围是独占的,即使在这种情况下它们应该是。

我可以想象这里使用了某种Dictionary<Range<int>, string>>,但它似乎仍然不足以提供我正在寻找的所有保证。或许可以使用多态性以一种更精简和可扩展的方式对这一概念进行建模?

对于这个简单的例子我很抱歉,但我确信这可以作为通用范围映射策略应用于其他更复杂的算法。

【问题讨论】:

    标签: .net oop design-patterns mapping range


    【解决方案1】:

    如果它是简单的将位置映射到位置线性增加并且结果增加相同数量的其他格式,那么可以使用简单的公式。

    对于您的等级字母示例,将“A”映射到 0,将“B”映射到 1 等很简单:

    int value = ...
    Character result = value -'A';
    

    大多数语言会将“A”映射到其 ASCII 值,因此从“A”中减去所需的值将产生“过去”A 的字母数。

    如果您需要更复杂的东西,例如范围映射,那么Replace Conditional Dispatcher with Command 模式(示例显示为here)可能是个好主意。

    如果你有更复杂的东西,那么像Chain of Responsibility Pattern。

    这是一个简单的例子:

    您需要创建一个接口,该接口具有确定您提供的 Range 是否适用于该实现的方法。

    IGradeMapper{
       bool accept(Range<int>);
    
       String computeGrade(Range<int>);
    }
    

    那么你有一个按顺序检查的IGradeMappers 列表:

    for(IGradeMapper mapper : list){
        if(mapper.accept(range)){
            return mapper.computeGrade(range);
        }
    }
    

    这种方式的好处是每个匹配器都是松散耦合的,如果需要,您可以稍后(甚至在运行时)实现并将新的匹配器添加到列表中。

    如果你是这两种模式中的任何一种,那么请尝试使测试的第一个条件成为最常见的条件,以使其运行得更快。

    【讨论】:

    • 非常好,正是我希望看到的那种答案。不幸的是,这不是一个计算的关系,正如你所看到的,我特别指的是问题中的学业成绩。您能否在这里使用责任链模式设计一个简单的示例?
    • 我刚刚注意到您对 OP 的编辑,对此感到抱歉。另外,我认为您的IGradeMapper 应该使用int 而不是Range&lt;int&gt;。这里的目的是将单个数字映射到一个等级,例如 A 的范围是 9->10。我想知道在这种情况下什么会更好:我可以创建多个映射器,在构造函数中传递区间和相应的字母,或者创建一些具体类型,其中硬编码区间和范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多