第四单元UML总结
本单元主题是基于UML的学习,具体实现为实现一个图书馆管理系统,图书馆内部设置书架(包括热门书架)、归还处、预约处、阅读室、书本自动查询机;提供借书、还书、预约、取书、查询书籍运动轨迹等功能;同时实现用户信用分机制。
正向建模与开发
正向建模是指从需求出发,先进行蓝图设计,再根据蓝图进行具体实现。这与本单元UML主题十分契合,因此在完成作业的时候,我选择先绘制类图,再进行具体实现,若在实现中遇见问题,则反过来修改类图,重新进行设计,形成一个正反馈过程。
根据需求我们可以初步提取部分类以及类的行为:
- Library: 管理图书馆内设施。
- Book: 表示图书。
- Bookshelf:管理在架图书。
- HotBookshelf:管理热门图书。
- AppointmentOffice:管理预约图书。
- BorrowReturnOffice:管理借阅归还图书。
- ReadingRoom:管理阅读书籍。
- BookManager:管理图书馆中所有图书的信息。
- User:表示用户。
然后分析各类之间的关联关系:
- Library:由Bookshelf、HotBookshelf、AppointmentOffice、BorrowReturnOffice、ReadingRoom、BookManager聚合而成。
- Book:与所有设施都关联,但唯独对Library不可见,Library若要使用Book,则必须通过BookManager来进行管理。
- HotBookshelf:继承Bookshelf,只需改变type属性即可,行为无需重构。
- 将Bookshelf、AppointmentOffice、BorrowReturnOffice、ReadingRoom、User抽象,同时实现BookBelonging接口,该接口只由getType(),sendBook(),receiveBook()方法组成。不同设施之间只需要通过send和receive两个方法进行类似通信的操作。
- 第三次作业可以添加接口方法即updateUserCredit(),但是由于仅有AppointmentOffice和ReadingRoom才会使用此方法,故偷懒未添加,但是若有后续迭代,此方法仍可添加。
在实现过程中,发现问题后重新反馈修改类图:
- 第一次作业中,涉及用户持有书籍数量影响借阅请求的规则。起初设计类图未考虑这一方面,直至实现的时候发现此规则判断实现较为繁琐,因此重新设计Rule类,提供isNumIlligal()方法。
- 很lucky的是,在第三次作业中,增加了信用分规则,由于Rule类的实现,因此只需添加isCreditIlligal()方法即可。
最后的UML类图如下:

感受:虽然正向建模过程中需要反复修改类图比较痛苦,但是本单元的架构是我认为除U3外我设计的最好的依此设计的架构,在迭代过程中没有重构,在添加新功能时也比较轻松,要是前两个单元也能做到好好设计,就不至于都出现那两个单元到第三次作业的重构行为了,太痛了。
追踪关系
- UML类图:
- 对应Java中类的实现,包括类的成员属性、实现方法以及类与类之间的关联关系。
- 类图在上。
- UML状态图:
- 描述Book的状态变化:本代码中体现在Book所处的书籍归属处的变化。
- 状态图:

- UML顺序图:
- 描述用户预约Book到取到书籍的过程:体现在发送预约请求后,图书馆内部各种类之间信息传递的时许过程。
- 顺序图:

大模型辅助
设计思维演进
U1:
- 将表达式根据文法规则进行递归下降解析,将表达式逐渐parse出表达式、因子、项等,在这些因子类中进行具体的运算。
- 引入工具类的思想:Parser、Lexer、PreProcessor、Printer等,将不同功能的代码进行分离,方便后续维护。
U2:
- 最重要的是学习了解决多线程问题的一种重要模式——生产者与消费者模式。本单元设计主要围绕着此进行设计:Requestable和Dispatcher之间、Dispatcher与Evalator;
- 同时学习了观察者模式:双轿厢电梯遇见冲突的时候通过观察者模式的设计来解决此问题。
U3:
- 本单元没有自己的设计,通过JML进行代码填写即可。
- 虽然没有自己的设计,但是可以反思课程组提供的JML的优秀范式:提供这些接口是如何协同完成此社交网络的如此复杂的所有功能。
- 同时,本单元是真正意义上的实现了设计与实现分离,我们无需烦恼设计的问题,只需关注具体代码的实现。本单元我觉得是真正意义让我感受到此分离法的意义,对我的U4影响以及帮助很大。
U4:
- Library进行统一管理、不同设施通过实现接口来完成各自的职责。
- Library根据接收到的用户请求来整体“指挥”各个设施的工作。
测试思维:
- U1:通过随机生成大量复杂数据,可以借助sympy进行检测。
- U2:测试代码也设置了电梯类,根据输出调整电梯,同时判断正确性。
- U3:根据JML判断正确性,同时结合JUnit和OkTest来进行检测。
- U4:尝试写交互式评测机,最后不了了之,最后决定手搓特殊数据检测。
课程收获
当初的OOpre的勇者们也是通关了OO这门课程,这其中有痛苦,有煎熬,但最终回首,发现这是一段令人难忘的课程体验。从一开始一周要撰写千行代码的倍感煎熬,到现在享受面对情景进行放飞自我的设计(实现代码还是煎熬哈),我面对的不再是一周内强制完成的Java代码训练,而是真正的一个情景,一个真正可以依靠我自己从设计到实现,再到测试的情景分析。
同时,OO也不是只是根据情景完成代码的课程,它教会了我们如何在两周一次的研讨课上互相分享心得,教会了我们如何共同协作搭建评测机,教会了我们如何利用大模型进行辅助编程,教会了我们真正的面向对象的思想,而不止于代码的编写。
最后感谢OO所有的老师以及助教,感谢OO这门课程。