对象模型: 数据模型:
![](https://i-blog.csdnimg.cn/blog_migrate/ba734e02f90e4a76a01c910bcc83d0fa.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/9c72e6da03dfd81a58e9437840f33f0f.jpeg)
Unit: 单位主表,一般保存度量单位的代码、文本描述(可能需要处理多语言问题)等
Unit_Ratio: 单位转换率
Quantity主要封装与单位相关的逻辑,例如:
person1.Height.Add(
8.5
, Unit.Get(
"
cm
"
)
);
person1.Height.Add( 0.03 , Unit.Get( " m " ) );
Quantity diff = person1.Height - person2.Height;
单位处理逻辑中一个主要功能是单位转换运算,例如Quantity相减的操作符重载代码类似如下:
person1.Height.Add( 0.03 , Unit.Get( " m " ) );
Quantity diff = person1.Height - person2.Height;
public
static
Quantity
operator
-
(Quantity left, Quantity right)
{
Quantity diff = new Quantity(left._amount, left._unit);
diff._amount += right._amount * right._unit.Ratio(left._unit);
return diff;
}
{
Quantity diff = new Quantity(left._amount, left._unit);
diff._amount += right._amount * right._unit.Ratio(left._unit);
return diff;
}
度量(Measurement)
度量是对数量模式的进一步抽象,书中以体检为例,进行一次体检就是得到一组各方面的度量数据,例如身高、体重、血压等,如果象上面那样在一个表中使用不同字段存储各个指标以及单位,自段会非常多,因此有了下面这个模式
对象模型:
![](https://i-blog.csdnimg.cn/blog_migrate/65cfc3d074c3fcfa101542d9035854bc.jpeg)
数据模型:
![](https://i-blog.csdnimg.cn/blog_migrate/6be890c7a59147810c06b0e4a3057f62.jpeg)
PhenomenonType2: 度量类型,例如长度、重量、体积等,每种度量类型关联多个度量单位(Unit)
示例数据:
![](https://i-blog.csdnimg.cn/blog_migrate/97b85e55ed9e810ca613bc5fa8dfe16b.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/d21f125f597298119aa00fea790ff007.jpeg)
1. 某个人体检结果(实际上应当有个体检对象)的各种度量(PhenomenonType)指标均保存在Measurement中
2. 对象模型中Measurement与Quantity分开,各司其职
3. 界面上让用户选择单位时可以根据度量类型(PhenomenonType)缩小可选择单位的范围,例如身高这个属性只能选择长度单位
4. 对于每种度量类型可以维护一个基本单位(Is_Basic),系统一些内部运算以基本单位为准,例如财务、库存的交易、月结盘点,ERP的MRP运算等
为简化终端用户对单位转换率的维护工作,可以只维护每种单位到基本单位的转换率,系统自动计算同一度量类型中任意两种单位之间的转换率,但系统也可以不将这个逻辑硬编码而做的更灵活,这是一种基本的业务设计、指导方式
测绘(Observation)
测绘是对上面两种模式的进一步抽象
度量模式虽然使用度量类型带来了更大的灵活性通用性,但考虑的仍然是 "数量+单位" 这种测量类型,以色盲这一体检项目为例,它仍然是一个评测指标,但评测结果一般表现为一组可选值: A类红色盲、B类红色盲、B类红色弱、B类绿色弱等
所以提取一个测绘基类(Observation),从它派生出两种类型: 度量(Measurement)和分类评测(CategoryObservation)
对象模型:
![](https://i-blog.csdnimg.cn/blog_migrate/11d40e73d8ab15e5cbb50929c7685f7e.jpeg)
数据模型:
![](https://i-blog.csdnimg.cn/blog_migrate/0583c4d2f3875dc389b336c5ca641238.jpeg)
CagegoryOption3: 每种分类评测(CategoryObservation)类型可选值列表
PhenomennonType3: 添加一个Observation_Type字段用来区分属于哪种测绘类型,例如1: Measurement, 2: CategoryObservation
用面向对象的手段,Measurement3、CategoryObservation3与Observation3之间为实现接口或继承基类的关系;使用结构化设计手段,他们之间只是弱关联关系,Martin在书中实现泛化一节有详细说明
上面图例可以理解为使用单表继承(Single table inheritance)实现这个继承关系,对于Measurement子类型Category_Option字段无效,对于CategoryObservation子类型Amount和Unit字段无效;CategoryObservation3和Measurement3因为行为上的差异而需要使用不同子类实现,Measurement3与Quantity3同样因为关注的职责不同而分离开;图中明显表现出多余、重复的气味,所以并不是一个优化设计方案,但对于理解Martin讲的Observation是什么正合适
转换率的时效性
指单位之间的转换随时间浮动,典型的是各种币别之间的汇率,这种情况下转换率需要添加有效时间范围,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/d219f4f5b1fa1c11e93bd470b9d0dbca.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/f5c98a54f869b2f6ee02c047f910ade4.jpeg)