1.2.5 维数合并(Dimension Combinations)
第三种很常见的测量方式/种类是按维数合并,很容易想像,例如,统计整个东北地区的销售额,这时需要提供的信息是维数和测量的类型,然后对东北地区下属的各个子区域的同类型测量对象进行合并,也就是说,按维数合并是在某个维数上针对某种测量类型的合并。
合并的计算方法一般来说是累加,但也不完全如此,例如,求平均值的操作就不是。
因此我们可以在测量协议的子类中增加一个类型:Dimension Combination,首先必须指明是针对哪一个Dimension 进行合并,然后对这种类型的协议增加一个约束(constraint),让它的输入参数为0(因为输入参数一般跟输出的类型一致);对这种测量的创建过程也跟前面提到过的差不多一样,只是将查找输入参数替换成查找Dimension 的下属对象就可以了。
可以针对每个Dimension 和Phenomenon Type 定义一种Combination;还要提到的是,可以针对每个Phenomenon Type 的Combination 定义比较测量(Comparative Calculations)。
1.3 范围(Range)
在判断某个数值是否落在某两个数值之间时最常见的是要用到范围(Range),范围一般由一对数值组成,而对范围的检查也需要同时检查它们两个。而Range 正是用一个单独的对象对这对数值进行整体表达,并提供一般的相关方法,例如检查某个数值是否落在它自己的区间里。
它的基类非常简单,包括两个表示上下限的属性start 和end;同时再提供一个include 方法,来判断范围。
我们可以用任何支持比较的数据类型作为范围的数据类型(在这里,可以用到c++中的模板类/参数化类的概念,在UML 表述中写成Range<T>的方式,如果你用的语言也支持的话);例如Range<number>,Range<date>;而实际上有许多的人,包括作者自己,一般都只用到这两种常用的数据类型,并引入了术语Number Range 和Date Range。
更复杂一点的Range 可能还设置了一种排序准则,就是将区间里的各种对象按某种方式排序的方法,
表现为一种方法(function);或者是包装了这种方法的对象。
对于开放区间,例如>6,我们可以用null 值代表一个无限值;然后在实现判断的时候会稍稍显得复杂
一点,不过对用户来说,他们不会看到这种复杂性,从而觉得接口很友好。还有一种办法是提供一些额外
的Range 创建方法例如Range.greatThan()。还要注意的是,如果范围支持的数据类型是连续的而不是离散
的(实数对于整数就是连续的),例如">6"的整数范围可以将下限设为7 来表达,而同样的实数范围你
大概不想设为6.0000000000001),那么最好再提供一对bool 值来辅助表达上限和下限是否包括在Range
中。
Range 类非常适合采用参数化类的方式,如果语言支持的话;如果语言不支持,可能需要建立在基类,或者为特殊的类生成子类;如果需要对上下限的对象进行其他的操作,那么向下转型将会是一场非常痛苦的经历。
我们习惯上用起始值(start 和end)来表示Range;也可以加上长度(length);如果一定要以start 和length,或者end 和length 来表达也是可以的,甚至可以三个都用,不过要定义这三个值之间的约束条件。
什么时候会用到Range 模式?作者说,他一直都在使用,用Range 比用一对数值好多了,而且编码也非常容易。而笔者也曾参照Range,实现了一个根据范围查比例的类,例如从1 到100 对应的比例是0.1,101 到200 对应的比例是0.2,等等,感觉非常好用。