• BUAAOO第二单元代码分析


    第一次作业

    设计思路与感想

    第一次作业是要求有捎带的电梯实现, 第一次作业是花费的时间比较长的一次,花费了很多的时间去思考架构的问题.起初是想要搞三个线程的:输入线程,调度器线程和电梯线程,想要搞一个连锁的生产消费模型,但是在调度器线程和电梯线程在交互的时候出现了一些问题.

    1. 对run方法操作最小化的思考,
      • 对于输入线程和调度器线程来说就是比较简单的,对于电梯线程我考虑了要不要添加一些非最小化的操作,比如:电梯加入moveTo()方法.
      • 这样的方法在while(true)里面是不合适的,完全可以通过每循环一次移动一楼
      • 这个moveTo具有占用大量时间的问题,因为上楼就要有0.4s的消耗,上楼这段时间没有办法执行下一次循环来响应请求.
      • 所以run方法中含有while(true)建议每次循环都做最少的事,由小组成一个大的
    2. 对于三个线程即:输入,调度器,电梯线程的思考
      • 这块我起初是想实现三个线程但是操作上还是出现了问题,虽然构建了流水线来搞,但是电梯线程有一个上下楼的等待时间,这个对于调度起来说,给不给电梯捎带请求是很难的一点,这个时候就需要加入一个电梯的返回来实现,而我没有这么做.
      • 我是直接将电梯线程join到了调度器线程里面,这个时候电梯内部没有了while(true), 等到电梯执行完了调度器再继续执行.
      • 交了作业以后,我发现其实此时的电梯线程已经没有必要再做成一个线程了,它完全就是一个普通的对象了.于是在下一次作业,将三线程变成了两线程
    3. 本次作业采用了als算法,性能不是很好,还是用look性能好一些.

    类图分析

    • 类之间调用的复杂度比较高,还是有一定的改进空间

    度量分析

    Method ev(G) iv(G) v(G)
    "Command.Command(boolean)" 1 1 1
    "Command.addCommand(int)" 1 3 3
    "Command.getCommand()" 1 3 3
    "Dispatcher.Dispatcher(LinkedList,Elevator,Command,boolean)" 1 1 1
    "Dispatcher.checkIfSomeBodyGetIn()" 3 2 3
    "Dispatcher.checkIfSomeBodyGetOff()" 3 2 3
    "Dispatcher.closeDoor()" 1 2 2
    "Dispatcher.downFloor()" 1 2 2
    "Dispatcher.getIn()" 3 4 4
    "Dispatcher.getOff()" 3 3 3
    "Dispatcher.isSameDir(PersonRequest)" 3 4 5
    "Dispatcher.openDoor()" 1 2 2
    "Dispatcher.run()" $color{red}{6}$ $color{red}{13}$ $color{red}{15}$
    "Dispatcher.setStop(boolean)" 1 1 1
    "Dispatcher.upFloor()" 1 2 2
    "Elevator.Elevator(LinkedList,Command,Integer,boolean)" 1 1 1
    "Elevator.arrive()" 1 1 1
    "Elevator.close()" 1 1 1
    "Elevator.down()" 1 2 2
    "Elevator.getFloorNumNow()" 1 1 1
    "Elevator.getIrq()" 1 1 1
    "Elevator.isRuning()" 1 1 1
    "Elevator.open()" 1 2 2
    "Elevator.run()" 1 5 5
    "Elevator.setRuning(boolean)" 1 1 1
    "Elevator.up()" 1 2 2

    有一个方法的复杂度比较高,其他的方法还好.这个run方法里面多次调用了elevator里面的方法,而且多次启动新线程,可能是导致复杂度上升的原因.

    时序图

    第二次作业

    设计思路与感想

    本次作业是多部电梯之间协同工作,且设计了容量问题,我是将上次的作业进行了优化,将上次作业中的调度器和电梯线程之间合并为了一个电梯线程,这样的话,多部电梯,就只用一个电梯类来刻画即可以达到目的,同时电梯内部的调度策略换为了LOOK,电梯间的调度策略是为每部电梯定义了一个函数:f(a,b,c,d,e,f);

    • a表示电梯所在的楼层
    • b表示电梯的运行状态上还是下
    • c表示该请求所在的楼层
    • d表示该请求要去往的楼层
    • e表示电梯外已有的等待人数
    • f表示电梯内已有的人数
    • 函数返回一个值来衡量电梯的负载情况

    主线程读到请求后,直接分配给f(a,b,c,d,e,f)值最小的电梯来运行.由于与上次的改动并不多,也就不会出现线程安全的问题,而且这样的调度策略在性能上也是比较好的一个动态调度方案.

    类图



    类图也比较简单,只有两个类,elevator类结合了上次作业的捎带功能,main方法加入了一个电梯之间的分发问题.

    度量分析


    本次作业中最大值是getfd()方法,这个方法就是上文中提到的为了调度所定义的f(a,b,c,d,e,f) ,可能在实现上还是有面向过程的思想,导致该方法循环复杂度极高.

    时序图

    第三次作业

    设计思路与感想

    • 本次作业是多部多类型电梯之间的调度.
    • elevator基本没有更改,只是增加了一些配置内容,这里是直接使用了type和if判断,这与面向对象的设计思想有不符的地方,但是为了各种安全性问题,还是决定不进行大改了
    • 因为上一次的类数过少,有些类它的内部可能干的事情太多了,于是又抽象出了两个调度器类,不过这次它不再是一个线程了,而只是一个管理者.同类型电梯之间的调度方案和第二次作业相同,抽象出了Dispacher类.不同类之间采用先拆分为直达请求的方法,然后为电梯分配,于是又有了个DispacherTop类.从上到下进行管理
    • 这次被hack出了线程安全问题,但是最后还是没有找到问题在哪,因为我是尽量减少共享对象的设计方案,所以可能是在增加电梯时的管理层级出现了问题.

    类图



    • 可以看到出现了跨层之间的调度,这个是因为请求拆分以后进入一个队列需要为电梯调用,那么拆分后的两条请求,第一条执行完毕需要告诉顶层的调度器去继续执行.

    度量分析



    • 类的复杂度比较高,原因在于我没有把请求队列,等待队列这些部分抽象出来,来降低耦合度.其实可以抽象出等待队列,来避免跨层之间的调度,而是都与等待队列来交互,实现解耦.

    时序图

    SOLID设计原则分析

    1. Single Responsibility Principle:单一职责原则:一个类应该只有一个发生变化的原因
    • 本次作业尽量做到单一职责原则,但是有些地方因为拆分为类比较复杂,于是选择了耦合.
    1. Open Closed Principle:开闭原则:一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭
      • 在每次作业中都有重新设计类图的结构,所以类都是改变过的,显然没有遵循到开闭原则.
    2. Liskov Substitution Principle:里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象
      • 没有使用继承,在第三次作业中使用了type,所以也没有遵循这个规定.
    3. Law of Demeter:迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
      • 没有遵循到这个设计原则,也正因为没有使用第三方来发送信息,所以导致耦合度较高
    4. Interface Segregation Principle:接口隔离原则:
      1.客户端不应该依赖它不需要的接口。
      2.类间的依赖关系应该建立在最小的接口上。
      • 未使用接口,同继承,增加了耦合度.
    5. Dependence Inversion Principle:依赖倒置原则:
      1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。
      2、抽象不应该依赖于细节,细节应该依赖于抽象。
      • 第三次作业中,上层模块依赖了底层模块,违反了依赖倒置原则.且没有实现抽象增加了耦合度
  • 相关阅读:
    Weblogic 12c 集群部署和session复制
    Weblogic 12c 集群环境搭建
    Programming In Scala笔记-第十九章、类型参数,协变逆变,上界下界
    这是最好的时光,这是最坏的时光 SNAPSHOT
    这是最好的时光 这是最坏的时光 v0.1.1.1
    鹅厂欧阳大神给年轻人的一些分享
    谈到电影,我们收获了什么
    那些被电影搞的日子
    Programming In Scala笔记-第十五章、Case Classes和模式匹配
    [CSharp]传一个包含多个属性的对象,只改变其中个别属性值的方法
  • 原文地址:https://www.cnblogs.com/donsome/p/12697495.html
Copyright © 2020-2023  润新知