软件构造学习(六)关于实验三的一些思考
这个实验目标是编写具有可复用性和可维护性的软件,主要使用以下软件构造技术:
1.子类型、泛型、多态、重写、重载
2.继承、委派、CRP
3.语法驱动的编程、正则表达式
4.设计模式
本次实验给定了多个具体应用,不是直接针对每个应用分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性)和更容易面向各种变化(可维护性)。其中使用了策略模式、访问者模式、装饰器模式和静态工厂模式。通过本次实验,是要更好地理解for reuse和with reuse,通过编程实践来巩固掌握的知识。实验主要面向聚餐选菜、商业表决和代表选举三种应用场景。他们的公有属性如下:
差异性如下:
一、ADT设计
本次实验中设计的ADT主要有:投票人、候选对象(学生、菜品、商业提案)、投票类型VoteType、选票项VoteType、选票Vote和投票活动Poll
还有就是Poll
二、Vote的equals方法为什么不能重写?
在编写Vote类时,我起初重写它的equals方法,将其更改为如果它其中包含的选票项相同,那么选票就相同。但是这样做没有考虑到的是有的应用场景的投票是匿名进行的,也就是每个选票Vote只会记录VoteItem而不会记录投票人是谁。所以当我尝试把选票添加到投票活动中的选票集合中时,如果不同的两个投票人对一个候选人给出了相同的得分,那么集合就会把这两个选票视作相等,就不会进行重复添加。因此两个投票人给出的投票就会只记录一张。所以不能重写Vote的equals方法,除非你能保证不用Map或者Set。
三、如何利用正则表达式完成VoteType的另一种构造方法
在这里补充 完成另一个构造方法 public VoteType(String regex),它输入一个遵循特 定语法的字符串,构造函数解析该字符串,进而构造出 VoteType 对象。该字符 串的语法规则如下: “喜欢”(2)|“不喜欢”(0)|“无所谓”(1) 其中,用双引号括起来的文字部分是一个投票选项,长度不超过 5,其中不 允许出现空格;用括号括起来的数字是投票选项对应的分数,可以是正整数、0 或负整数,不能带小数,正整数不需要使用“+”,但负整数需要使用“-”;不同 的投票选项之间用“|”隔开。 也可以用如下形式: “支持”|“反对”|“弃权”。
这里我是利用正则表达式和捕获组的形式来实现的,考虑到两种格式均要求将投票选项利用“|”来分割,所以我先用以下两种格式来匹配,如果匹配失败,说明没有用“|”来分割,那么直接抛出异常并提示然后退出:
如果匹配成功,那么利用“|”来分割选项,此时分割后得到的字符串数组的形式就是“支持”或者“喜欢”(2)的其中一种。所以为这两种形式编写正则表达式,此外,由于要检测选项长度和是否满足小于5以及获取选项对应的分数,所以此处使用捕获组,一个捕获选项,一个捕获选项对应的分数。具体实现如下:
不同的格式错误原因,都会抛出IllegalVotetypeException,但是会携带不同的异常信息,方便调用者根据不同的提示来进行更改。
四、如何使用Junit5进行异常测试
这里的测试一是输入正确的格式,来检测构造后得到的选项及其分数是否与预期结果一致;二是输入不同的错误格式,检测是否抛出异常以及携带的异常信息是否与错误原因相一致。大致的测试方法如下: