北航OO(2020)第二单元博客做业

北航OO(2020)第二单元博客做业

设计策略分析(多线程视角)

本单元的三次做业中,我采用了类似的策略:采用输入线程与电梯线程经过线程安全的调度器进行交互的方式。这种方式基本属于生产者-消费者模式。在调度器的设计方面,我主要采用synchronized关键字结合wait和notify方法完成互斥访问和同步控制。编程

Homework 3 SOLID分析与可扩展性分析

Single Responsibility Principle

Elevator类有且仅有一个public方法:run方法,仅仅负责执行电梯的运行逻辑。数组

Main类有且仅有一个public方法:main方法。但main方法既负责建立线程,又负责输入的处理与结束,具备多重责任。能够采起建立新的输入类和输入线程的方法解决这个设计问题。安全

Dispatcher类具备多个public方法,但每一个方法都有惟一肯定的职责,经过下面章节中UML类图便可确认这一特性。Dispatcher类负责将请求放置于每一楼层,供Elevator取用,知足了SRP原则。多线程

FloorConverter类有两个public方法,负责将楼层号与数组下标相互转换,知足了SRP原则。架构

FloorSelector类有两个public方法,分别用来判断当前层是否能够停靠和选择乘客的目的楼层。这两个职责都须要电梯的停靠信息,并且逻辑联系较为紧密,所以能够置于同一类中完成。测试

Open Close Principle

本次做业中除继承Thread类外没有使用任何继承,几乎都是经过修改已有实现完成新增功能,违反了OCP原则。spa

Liskov Substitution Principle

本次做业中除继承Thread类外没有使用任何继承,所以该原则无从体现。线程

Interface Segregation Principle

本次做业中没有使用任何接口,所以该原则无从体现。设计

Dependency Inversion Principle

本次做业中除继承Thread类外没有使用任何继承,且没有使用任何接口,所以该原则无从体现。3d

可扩展性

经过上面的分析能够看出,扩展功能几乎必定须要经过改写已有的实现来完成。但因为类的public方法职责都较为明确,这样的设计能够为功能的扩展带来必定的便利。

基于度量的程序结构分析

Homework 1

代码度量

Type Name Method Name LOC CC PC
Dispatcher Dispatcher 10 2 0
Dispatcher setFinished 6 1 0
Dispatcher addRequest 13 2 1
Dispatcher getRequests 14 2 2
Dispatcher getTask 30 9 1
Elevator Elevator 11 2 1
Elevator run 39 10 0
Elevator stopOnFloor 20 2 1
Elevator getOn 7 2 1
Elevator getOff 7 2 0
Elevator go 10 1 0
Main main 23 3 1
Type Name NOF NOPF NOM NOPM LOC WMC NC DIT LCOM FANIN FANOUT
Dispatcher 5 1 5 5 80 16 0 0 0.0 2 0
Elevator 6 0 6 2 102 19 0 0 0.0 1 1
Main 0 0 1 1 25 3 0 0 -1.0 0 2

类图

本次做业构建了三个类。这些类的封装较好,对外暴露的方法较少,且都具备明确的职责。大部分方法具备明确的职责,也较为简洁。可是,Elevator类的run方法展开了电梯的一次运行逻辑,总体较为复杂;Dispatcher类的getTask方法也较为复杂,不便改动和维护。

Homework 2

代码度量

Type Name Method Name LOC CC PC
Dispatcher Dispatcher 10 2 0
Dispatcher setFinished 6 1 0
Dispatcher addRequest 13 2 1
Dispatcher getRequests 23 6 3
Dispatcher getTask 35 9 1
Dispatcher getUpperTask 8 3 1
Dispatcher getLowerTask 8 3 1
Elevator Elevator 12 2 2
Elevator run 39 10 0
Elevator stopOnFloor 20 2 1
Elevator getOn 7 2 1
Elevator getOff 7 2 0
Elevator go 10 1 0
FloorConverter indexToFloor 7 2 1
FloorConverter floorToIndex 7 2 1
Main main 27 4 1
Type Name NOF NOPF NOM NOPM LOC WMC NC DIT LCOM FANIN FANOUT
Dispatcher 6 1 7 5 111 26 0 0 0.0 2 1
Elevator 8 0 6 2 105 19 0 0 0.0 1 2
FloorConverter 0 0 2 2 16 4 0 0 -1.0 2 0
Main 0 0 1 1 29 4 0 0 -1.0 0 2

类图

本次做业与上一次做业架构极为类似,只是多了FloorConverter类。所以优缺点与上次大致相同,在此再也不赘述。

Homework 3

代码度量

Type Name Method Name LOC CC PC
Dispatcher Dispatcher 10 2 0
Dispatcher setFinished 8 2 0
Dispatcher addRequest 13 2 1
Dispatcher elevatorAddRequest 9 2 2
Dispatcher getRequests 12 2 4
Dispatcher filterRequests 19 4 5
Dispatcher decreaseRequestCount 6 2 0
Dispatcher getTask 35 9 2
Dispatcher hasValidRequest 10 3 4
Dispatcher getUpperTask 11 4 2
Dispatcher getLowerTask 11 4 2
Elevator Elevator 28 5 3
Elevator run 40 10 0
Elevator changeDirection 8 2 0
Elevator stopOnFloor 18 2 1
Elevator getOn 10 2 1
Elevator getOff 15 3 0
Elevator go 12 1 0
FloorConverter indexToFloor 7 2 1
FloorConverter floorToIndex 7 2 1
FloorSelector isStoppable 12 4 2
FloorSelector selectFloor 15 5 4
FloorSelector selectFloorA 6 2 1
FloorSelector selectFloorB 18 6 3
FloorSelector selectFloorC 24 8 3
Main main 33 6 1
Type Name NOF NOPF NOM NOPM LOC WMC NC DIT LCOM FANIN FANOUT
Dispatcher 6 1 11 7 152 36 0 0 0.2727272727272727 2 2
Elevator 10 0 7 2 143 25 0 0 0.0 0 3
FloorConverter 0 0 2 2 16 4 0 0 -1.0 3 0
FloorSelector 3 0 5 2 80 25 0 0 1.0 2 1
Main 0 0 1 1 35 6 0 0 -1.0 0 1

类图

本次做业构建了五个类。这些类的封装较好,对外暴露的方法较少,且都具备明确的职责,类间的协做关系也较为明确。大部分方法具备明确的职责,也较为简洁。可是,与前两次做业同样,Elevator类的run方法仍然展开了电梯的一次运行逻辑,总体较为复杂;Dispatcher类的getTask方法也较为复杂,不便改动和维护。

UML时序图

因为三次做业的线程交互模式较为相似,所以统一绘制UML时序图以下。

Bug分析

本单元做业在公测和互测中未出现任何bug。

在第三次做业的开发过程当中,因为Dispatcher类的getTask方法和getRequests方法判断请求是否为空的标准不一致,个人电梯线程在一些状况下出现了轮询,致使在中测中出现了CTLE的现象。我在本地经过在JProfiler中观察线程状态及CPU时间,并在程序中打印log的方式,最终定位了bug的位置,并进行了修复。

Hack策略分析

本次做业同第一单元不一样,须要作到在线交互。所以,本次做业的测试要求更高。可是,因为摸鱼心切,我仍然采用了手动构造测试用例的方法。所以,本单元我未能发现他人的任何bug。

心得体会:线程安全与设计原则

经过本单元的三次做业,我对Java多线程编程有了一个初步的认识,并了解了一些简单的互斥访问与同步控制的方法。在多线程编程中,经过线程安全的共享对象来完成线程间交互是十分清晰而简洁的方式。经过对象锁,可使该对象在同一同步块内只能被一个线程访问,且不会被打断。再结合wait和notifyAll方法,能够避免轮询,高效利用CPU资源。此外,在设计中遵循SOLID原则及一些其余重要的设计原则也是十分重要的,这些原则保证了程序结构的清晰性和良好的可扩展性。在本单元做业中,部分设计原则未能体现甚至有所违背,在从此的编程中会多加注意。

相关文章
相关标签/搜索