2014-03-31 75 views
0

这是一个简单的例子,我想先揭示问题。优雅的数字 - >字母学术成绩映射

考虑你有一堆数字,范围从0到10,并且你想把它们映射到字母等级(A,B,C,D,F)。

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

问题是:什么模式可以用来使这个更强大,也许更多的解耦?例如,如果我有10个数字范围而不是5个数字范围,那么我将不得不编辑这个单一方法来添加其他5个个案。我也不能保证我的范围是排他性的,尽管它们应该属于这种情况。

我可以想象在这里使用的排序的Dictionary<Range<int>, string>>,但它仍然不足以提供我正在寻找的所有保证。也许人们可以用多态性来以更简洁和可扩展的方式对这个概念进行建模?

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

回答

1

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

对于你的等级信例如,映射“A”为0,“B” 1等很简单:

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

大多数语言将“A”映射到它的ASCII值,减去你想要的值从'A'将产生字母“过去”A的数量。

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

如果你有更复杂的东西,然后像Chain of Responsibility模式。

这里有一个简单的例子:

你需要做,有一个方法来确定您所提供的范围将这种执行工作的接口。

IGradeMapper{ 
    bool accept(Range<int>); 

    String computeGrade(Range<int>); 
} 

那么你有是为了检查的IGradeMapper个清单:

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

关于这种方式的好处是匹配器均loosley耦合,并且可以实现与中添加新的如果你愿意,可以在后面的列表中(即使在运行时)。

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

+0

非常好,正是我希望看到的那种答案。不幸的是,这不是一个计算关系,因为我特别提到了问题中的学术成绩。你能否在这里设计一个使用责任链模式的简单例子? – julealgon

+0

@julealgon更新回答 – dkatzel

+0

我刚刚注意到你在OP上的编辑,对此抱歉。另外,我认为你的'IGradeMapper'应该使用'int'而不是'Range '。这里的意图是将单个数字映射到等级,因为例如A的范围是9-> 10。我想知道在这种情况下会有什么更好的效果:我可以在构造函数中创建多个传递区间和相应字母的映射器,或者创建一些具有硬编码内部区间和范围的具体类型。 – julealgon