模型

动机
- 规范市场模型和结构,为市场的交互者提供标准的行为模式;
- 提供符合规范的最简易实现;
- 实现数据和算法分离;
- 实现数据的可配置,以及数据结构的可替换;
- 实现算法的可替换;
- 提供灵活的扩展性,并对扩展过程进行规范;
- 充分利用Spring容器的特性,在面向Spring3的同时为Spring2.x提供兼容包装层;
- 实现数据和算法分离;
行动
命名对象
市场中的对象是可以识别的,而且通常是通过名字识别,称这些对象为命名对象:
1 public interface NamedObject { 2 String getName(); 3 void setName(String name); 4 } 5有些对象是通过Identity或者Code之类的属性唯一识别。为了编程方便,称这个Identity和Code就是Name,因此这里的name是一个广义上的含义,表示可以唯一识别。
图表1中的市场、各类管理器以及被它们管理的对象都是命名对象。
市场对象和市场对象管理器
1 public interface Managable<T extends Managable<T>> extends NamedObject { 2 public ManagerOf<T, ? extends MarketModel> getManager(); 3 public void setManager(ManagerOf<T, ? extends MarketModel> manager); 4 } 5市场中的对象和对象管理器有着管理和被管理的关系,一个特定类型管理器管理着一个或多个这种类型的对象。因此市场对象和市场对象管理器有着以下的特征:
1 public interface Managable<T extends Managable<T>> extends NamedObject { 2 public ManagerOf<T, ? extends MarketModel> getManager(); 3 public void setManager(ManagerOf<T, ? extends MarketModel> manager); 4 } 5模块为所有的管理器提供了基本的必要支持:CommonMarketManagedObject和 MarketObjectManager,市场对象继承CommonMarketManagedObject,而市场对象管理器则继承MarketObjectManager即可。
加权
在市场的模型中,使用以系列的加权来观察和设置市场。当前使用的加权有维度有货种,航线和时间。其中时间的加权自变量是连续的,而货种和航线的加权自变量是离散的。在业务中,决定了加权维度货种和航线是正交的(平行的),而时间维度是嵌套的。在实际使用中,正交加权系和当成嵌套加权系处理,反之则不行。所以,在当前的市场模型下,
1 public interface Weight{ 2 String getName(); 3 WeightSeries getWeightSeries(); 4 double getValue(); 5 } 6 7 public interface WeightSeries { 8 // 加权系列的名称 9 String getName(); 10 11 // 加权系列的加权表 12 List<Weight> getWeights() 13 14 // 获取指定名称加权点的子加权系列,如果加权点不存在,返回null 15 WeightSeries getChildSeries(String weightName); 16 17 // 求取指定加权所占的百分比,如果加权不存在,返回0.0% 18 double getPercent( String weightName); 19 20 // 求取加权路径上的百分比;加权路径,排在前面的先加权;如果加权路径不正确,返回0.0% 21 double getPercent(List<String> weightNames); 22 } 23加权系应该是货物种类 > 航线 > 时间,或者是 航线 > 货物种类 > 时间。
市场时钟
市场是随时间变化而变化的。在同一个时刻,市场的状态是相同的,只能有一种。因此在这个角度,可以认为市场的原始驱动力量是时间。考虑到系统的使用方式,模拟市场中的终具有现实客观始终以外的其他附加属性:1) 可操控性:停止、启动;2) 可跳跃性:不连续现实客观时间也可以在这个时钟上表示为连续的。
为了符合上述要求,市场时钟额外提供了一个时间记录器。为了使关于市场时钟时间的编程规范统一,模块定义了接口ClockWatcher,并提供了其管理接口和缺省的实现。
市场时钟部分相关的程序结构如下图所示:

【注意事项】对于耗时较多的ClockWatcher实现,应实现为独立的线程,或者实现一个缺省启动新的工作线程的ClockWatcherManager。