在lab3中,要求实现三个维度的局部特征变化,提供了六个方案。出于实现的便捷性和合理性,我使用了不同方案增加三个特征。
空白
第一个特征是空白,初始化时一定是空白的,故要做的是使时间轴能判断是否存在空白。
“空白”这个概念是相对“完整”而言的,在结构上需要规定时间轴的长度,增加一个新的属性,并且这个长度可以由客户端规定并查看;而检查是否空白不能在插入或移除等原有mutator中判断,这是不合理的,故不适用装饰器模式,更适合使用继承或组合以拓展。
这里我使用方案5 CRP组合复用,使用委派的方式,传入的参数是IntervalSet或MultiIntervalSet,可选参数为时间轴的开始时间和结束时间。
具体实现上,分别为两种时间轴设计空白判断类,完成前者的功能后,后者只需要把所有时间放到一个时间轴上,转换为前者再复用即可。功能设计上设置了判断是否空白和获取空白的时间段,为应用开发做准备。
重叠
第二个特征为重叠,时间轴只可能是允许重叠或不允许重叠,不存在转换,而基本的时间轴是允许重叠的,所以需要做的是使装饰器增加不可重叠的特性。想要保持不可重叠是合理的,且只要在被改变时进行判断就能保持这种特性,故只要重写mutator中的insert,在插入前判断会不会产生重叠即可。
这种修改用装饰器模式是最方便的,采用委派需要在子类中重写方法,采用继承会导致组合爆炸,而装饰器就是非常轻便的解决方案。
按照装饰器模式进行设计,分别为两个数据结构创造自己的装饰器父类和子类,重写insert方法。先写IntervalSet的装饰器,MultiIntervalSet创造出一个用这个装饰器修饰的IntervalSet,就可以复用已经写好的insert,还要重写remove方法,实时调整内部的IntervalSet。
![](https://img-blog.csdnimg.cn/direct/6b396d84a3cb42d784c9334db6955c6f.png)
周期性
第三个特征为周期性,即一个事件可以周期性地出现在时间轴上,由于事件重复出现,只针对MultiIntervalSet设计。要实现这个特性,就得确定周期的长度和周期的数量,暗含了周期的最大长度;同时由于需要判断时间是否具有周期性,就需要扩展新的方法,为了快速插入周期性时间,而不是让客户端逐个插入(还可能出错),就需要设计新的插入方法。
装饰器模式并不适用,而CRP方案又很别扭,“周期”是固有的特性而不是可有可无的方法,故选择使用继承的方案拓展该方案。
在继承树上,拓展新的接口,接口继承MultiIntervalSet接口,增加按周期插入事件和检查事件出现是否有周期性的方法,这里把事件的周期性作为可选的,所以保留了原有的insert方法。实现类在通过继承CommonMultiIntervalSet复用已有的方法,同时实现新方法。
总结
![](https://img-blog.csdnimg.cn/direct/327b360a9fb34671a4e7f280732f4343.png)
![](https://img-blog.csdnimg.cn/direct/4123da4ad2f842bf9f55f889ea3503f7.png)
粗略绘制了两个图表达三种关系,上图中
1.MultiIntervalSet复用了IntervalSet没有画出,空间不够
2.IntervalSet和MultiIntervalSet实际上没有委派给BlankCheck任何功能,而是在需要“检查空白”的具体类中产生委派关系,这里的delegation只是表达特征的实现方法
在完成实验任务时,并没有选择一种方法死板地完成,而是针对各个特性的含义,考虑实现难度,综合运用多种方案实现,(虽然有点担心实验会被扣分)在实际应用中,也应熟悉各种设计方式,按照业务需求灵活设计实现方案,在正确性的基础上提高灵活性和可维护性。