面向对象第二单元总结

一、设计策略

第一次作业

任务描述:完成单部多线程傻瓜调度(FAFS)电梯的模拟。

设计综述:考虑到接下来的两次作业任然是电梯相关,在完成这次作业的时候就直接

使用了捎带策略。用了两个线程,一个呼叫一个运行,没有调度器,完成需求是靠电

梯控制器主动请求获得新需求。

系统组成:一个呼叫器,一个电梯控制器,一个电梯,一个共享任务表。

呼叫器:往共享任务表里增加需求;

电梯控制器:因为电梯的运行时,有很明显的状态划分,状态的转变也有很

清晰的界限,所以考虑用状态机来设计电梯的运行;为了使得架构清晰,控

制器只能对电梯发指令,不可以影响电梯运行。

电梯:为了使得架构清晰,电梯模拟成真实电梯,可以上下楼,开关门,进

出人,除此之外没有其他逻辑,是单纯的机械电梯。

运行时策略:呼叫器作为一个线程,时刻监听用户需求;电梯控制器作为一

个线程控制电梯运转,一旦电梯没有目标了,立即从共享任务表里取离自己

最近的任务去完成,途中会稍带,并实时更新目的地。

第二次作业

任务描述:完成单部多线程可捎带调度(ALS)电梯的模拟。

设计综述:在第一次作业中已经实现此算法,稍加修改就完成了。

系统组成:同第一次作业。

运行时策略:同第一次作业。

第三次作业

任务描述:完成多部多线程智能(SS)调度电梯的模拟。

设计综述:四个线程;首先希望能在前两次作业的基础上做修改,先修改电梯类,使

得其能初始化成为题设要求的三个不同的电梯。在增加一个静态类以及相关方法,本

意是将其作为一个调度器线程使用,但后来考虑到之前的工作没有做这方面的设计,

如果要实现需要很大的修改架构,于是决定用加锁静态类实现,由电梯主动调用此类

进行需求分配。

系统组成:一个呼叫器,一个电梯控制器,一个电梯,一个共享任务表,一个请求任

务类。

呼叫器:往共享任务表里增加需求;

电梯控制器:沿用前两次作业的设计,作一定修改:不再是电梯控制器进

行空闲时安排任务,而是通过一个调用共享类进行任务分配。

电梯:沿用前两次作业的设计。

请求任务类:关联共享任务表,同时自己维护一个请求队列,当被调用时,

根据请求队列进行任务安排。

运行时策略:呼叫器作为一个线程,时刻监听用户需求;三个电梯控制器作为三

个线程控制三个电梯运转,一旦某一个电梯控制器没有目标了,通过调用共享任类进

行任务安排,同时删除需求队列中自己能捎带的需求,队列中需求能否捎带通过一个

静态方法判断,与三个电梯可停靠楼层有关,此捎带是能带则带,不考虑性能。

二、基于度量分析程序结构

第一次作业 

    • 数据度量:

  方法中列出复杂度高的部分,由下图分析:

  RunElevator的run()方法中,用while和switch实现了电梯的七个状态转换的逻辑,所以圈复杂度较高,但维护起来未必很困难。

  同样在RunElevator的searchForDestiny方法,用一个循环遍历邻近楼层,同时在满足条件是return,复杂度也比较高,或许不符合OO的要求。

  类中也是RunElevator的复杂度高,究其原因,或许是因为没有调度器的缘故,电梯控制器RunElevator需要负责电梯运行以及从需求池里获取请求两个功能。

    • 类图:
      同样延续上个分析的结论,RunElevator负责的功能比较多,不是单一的,所以导致这个类比较臃肿,在整个结构上看也是一个不够完善的地方。

    • UML协作图:

    • SOLID设计检查:

SRP:不符合,RunElevator类有获得请求和ALS调度执行两个功能,导致其过于臃肿,影响了整个结构的整洁与可维护性。

OCP:不符合,如果增加电梯的数目,因为没有调度器的缘故,需要考虑两个电梯fetch请求时的冲突,需要对RunElevator进行一定的改写。

LSP:未使用继承。

ISP:基本符合,对于写的大多数类,能隐藏的方法,我都private,在本次作业中,或许是对锁的理解不够,共享需求表我专门写了一个入口函数,等于说该共享类对外只有一个接口。

DIP:基本符合,类图上表示的比较清晰。

 

第二次作业

    • 数据度量:
      沿用了第一次作业的设计,基本上没有做什么修改,对比第一次作业其实数据上没什么区别

    • 类图:

 

    • UML协作图:

    • SOLID设计检查:

SRP:不符合,RunElevator类有获得请求和ALS调度执行两个功能,导致其过于臃肿,影响了整个结构的整洁与可维护性。

OCP:不符合,如果增加电梯的数目,因为没有调度器的缘故,需要考虑两个电梯fetch请求时的冲突,需要对RunElevator进行一定的改写。

LSP:未使用继承。

ISP:基本符合,对于写的大多数类,能隐藏的方法,我都private,在本次作业中,或许是对锁的理解不够,共享需求表我专门写了一个入口函数,等于说该共享类对外只有一个接口。

DIP:基本符合,类图上表示的比较清晰。

 

第三次作业

    • 数据度量:
      因为沿用了前两次作业的状态机设计思路,(这里的ElevatorController其实就是之前的RunElevator,改名只是觉得这样命名更好),当然因为分离了请求与控制两个功能,电梯控制器空闲时寻找需求的功能通过调用MasterController来实现(本来是打算把它变成线程的,但是后来发现不用更好写,于是就成为了非线程类)。所以电梯控制器的复杂度稍微降低了一点,当然因为题目的要求与我的设计,MasterController其实需要考虑很多东西,canDoApart是判断可否捎带某层楼的一些请求的,这个判断逻辑设计的比较复杂,用了很多循环,导致它的圈复杂度较高,相应的也提高了MasterController的复杂度。

    • 类图:
      共享需求表由三个类共享,运行时由四个线程和一个对象共享,一个呼叫线程需要增加,三个电梯线程需要取出以及放回,一个MasterController对象需要搜索来拿牌任务。EleProducer是根据题设生产三个电梯对象用的。

    • UML协作图:

    • SOLID设计检查:

      SRP:基本符合?相比于前两次作业,这次作业分离了请求和执行两个功能基本符合单一职责原则。

      OCP:因为增加电梯的数目,对RunElevator进行一定的改写……在数目上的改变想必只需要扩展了,这方面的OCP原则满足了。

      LSP:未使用继承。

      ISP:基本符合,对于写的大多数类,能隐藏的方法,都private。

      DIP:基本符合,类图上表示的比较清晰。

三、BUG分析

三次作业公测互测均未被发现bug

四、测试方法
    
本单元作业实现了自动化测试,自我测试效果不错(在没有被gank了),测别人的bug效果没有(没有成功过):

    1. 编写随机数据生成器
    2. 通过sleep进行定时输入
    3. 编写脚本批量测试
    4. 编写结果检查器

五、心得体会
   
 在第一单元结束时,深刻的体会到了架构的重要性,所以在本单元一开始时,就没有专注于题目本身,希望可以写出一个三次作业都不做修改的好结构,但是似乎走错了道路……

    以题目为导向,在一开始傻瓜式调度的时候就直接考虑了捎带算法,于是“刚好”第二次作业就是ALS调度电梯,在当时确实自认为干得不错,果然基本上只要稍加修改就可以用了,但其实这不是结构设计的优秀,完全是瞎猫碰上死耗子,结果第三次作业时费了很大的脑筋,尽管不至于重写重构,但也大费周折。

    究竟要怎么写一个好的结构,我想除了码代码前的深入剖析,还需要学习很多理论模式,或许才会事倍功半吧~

    多线程的使用其实刚好和操作系统正在讲的内容相得益彰,两门“重课”难得的在同一时间讲同一概念,确实令人学的舒爽,可以说这几周只要重点关心线程即可,着实令人学到了很多东西。

转载于:https://www.cnblogs.com/YeSiyuan/p/10759005.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值