电梯系统OO设计

35 篇文章 0 订阅
10 篇文章 0 订阅

理论上应该先黑盒用例,分析需要求,系统边界的输入输出,再白盒类图。 但是对于现实世界模拟的OO,个人感觉先emulate现实世界,初步识别类和类之间的关系,再用用例和顺序图丰富、修正类图。

识别类,最主要的原则是封装,数据和数据的操作封装成一个类:

轿厢 box:封装轿厢的状态:位置、方向、静止还是运动,capacity,  pickup列表,目的地列表

楼building:用户请求电梯的媒介,和轿厢box有个一对一关联关系,向轿厢box发call消息,轿厢到达某层,向building发某层open的消息。

从控制驱动的角度,有2种控制流(主动对象)

1)轿厢box:不停地运转,根据请求的情况,运行或者停止等待信号

2)人:1是人向building发消息,building再 forward到box;2)是人向轿厢发消息,设置要去的目的地楼层

和VODController类似,内部一个驻留线程,类似一个状态机运行着,同时多个点可以接收异步消息更新数据。

亮点是一个事件机制,每经过一层,触发一个positionChanged的事件

总结:OO系统,就是一个互相发消息的对象系统,对象之间靠消息交互

常见的控制流模型:

1) 顺序执行,exit

2)无专门驻留线程,完全消息驱动,类似一般的web service,request/response模式。

3) 有一个驻留线程在run, (定时运行或者受信号控制),同时也可以接受异步消息更新数据,为社么说是异步消息,因为它只是通过update数据来影响状态机的运行,不需要返回什么结果。基于工作队列的处理系统也属于这种模型,但更简单,FIFO处理就行,电梯模型的复杂在于,系统会根据当前所有request的情况做一个调度,并不是简单的FIFO。

class Box {
	int direction; // 0 up, 1 down, 2 stopped
	int currentPos; //current position
	int capacity;  // max load
	final static int   MAX_FLOOR = 100;
	volatile boolean destinations[] = new boolean[MAX_FLOOR]; 
	volatile boolean pickups[][] = new boolean[MAX_FLOOR][2]; //0 for up, 1 for down
	int highestTo = -1; // the farest upper floor to go
	int lowestTo = -1; // the farest lower floor to go
	volatile boolean on = true; //on or off
	Building building;
	int numRequest = 0;
	Object signal = new Object();
	
	public void call(int floor, int direction) { 
		synchronized(signal) {
			if (!pickups[floor][direction]) {
				pickups[floor][direction] = true;
				++numRequest;
				if (highestTo < 0 || floor > highestTo) highestTo = floor;
				if (lowestTo < 0 || floor < lowestTo) lowestTo = floor;
				signal.notify();
			}		
		}
	}
	public void setDestination(int floor) {	
		synchronized(signal) { 
			if (!destinations[floor]) {
				destinations[floor] = true;
				++numRequest; 
				signal.notify();
			}		
		}
	}
	public void shutdown() { 
		on = false; 
		synchronized(signal) {			
			signal.notify();
		}
	}
	
	private void open() {building.open(currentPos); /*first open the building door, then the box's*/ } 
	private void close() {building.close(currentPos);}
	private void stop() {}
	private void positionChanged() {	
		if (pickups[currentPos][direction] || destinations[currentPos]) {
			stop();
			open();
			//Thread.sleep(5000);
			close();
			synchronized(signal) {
				if (pickups[currentPos][direction]) {pickups[currentPos][direction] = false; --numRequest;}
				if (destinations[currentPos]) {destinations[currentPos] = false; --numRequest;}
				if (highestTo == currentPos) highestTo = -1;
				if (lowestTo == currentPos) lowestTo = - 1;
			}
			//resume();
		}
	}
	private void run() {
		while (on) {
			synchronized (signal) { 
				if (numRequest == 0) {
					direction = 2; //stopped
					signal.wait(); //wait signal here if no jobs to do					
				}
				//decide up or down, handle upper request first.
				if (highestTo > 0 ) direction = highestTo > currentPos ? 0 : 1;
				else if (lowestTo > 0) direction = lowestTo < currentPos ? 1 : 0;
			}
			
			if (direction == 0) { //up
				for (int i = currentPos + 1; i <= highestTo; ++i) {
					++currentPos;
					positionChanged();
				}
			}
			else if (direction == 1) {//down
				for (int i = currentPos - 1; i >= lowestTo; --i) {
					--currentPos;
					positionChanged();
				}
			}
			
		}
	}
}
//楼building:用户请求电梯的媒介,和轿厢box有个一对一关联关系,向轿厢box发call消息,轿厢到达某层,向buildng发某层open的消息。
class Building {
	Box box;
	public void call(int floor, int direction ) { box.call( floor,  direction);}
	public void open(int floor) {}
	public void close(int floor) {}
}



八、 实验内容和要求: 要求根据下面的功能说明描述实现模拟电梯控制软件 (一)电梯配置 1. 共有1个电梯 2. 共有maxfloor层楼层。maxfloor=9。 3. 中间层每层有上下两个按钮,最下层只有上行按钮,最上层只有上行按钮。每层都有相应的指示灯,灯亮表示该按钮已经被按下,如果该层的上行或者下行请求已经被响应,则指示灯灭 4. 电梯内共有maxfloor个目标按钮,表示有乘客在该层下电梯。有指示灯指示按钮是否被按下。乘客按按钮导致按钮指示灯亮,如果电梯已经在该层停靠则该按钮指示灯灭 5. 另有一启动按钮(GO)。当电梯停在某一楼层后,接受到GO信息就继续运行。如果得不到GO信息,等待一段时间也自动继续运行。 6. 电梯内设有方向指示灯表示当前电梯运行方向。 说明:由于本次实验不使用可视化框架,所以无法作到从图形界面上获取按钮请求。因此电梯按钮的设计,不在图形界面上体现,仅用来设计键盘的模拟输入。 (二)电梯的运行控制 1.电梯的初始状态是电梯位于第一层处,所有按钮都没有按下。 2.乘客可以在任意时刻按任何一个目标钮和呼叫钮。呼叫和目标对应的楼层可能不是电梯当前运行方向可达的楼层。 3. 如果电梯正在向I层驶来,并且位于I层与相邻层(向上运行时是I-1层或者向下运行时是I+1层)之间,则因为安全考虑不响应此时出现的I层目标或者请求。如果电梯正好经过了I楼层,运行在I楼层和下一楼层之间,则为了直接响应此时出现的I层目标或者请求,必须至少到达运行方向上的下一楼层然后才能掉头到达I楼层(假设掉头无须其它额外时间),如果I楼层不是刚刚经过的楼层则可以在任意位置掉头,此时掉头后经过的第一个楼层不可停。 4. 电梯系统依照某种预先定义好的策略对随机出现的呼叫和目标进行分析和响应。 5. 乘客数量等外界因素(可能导致停靠时间的长短变化)不予考虑。假设电梯正常运行一层的时间是5S,停靠目标楼层、上下乘客和电梯继续运行的时间是5S。 6. 当电梯停靠某层时,该层的乘客如果错误的按目标或呼叫按钮都不予响应。 7. 电梯停要某一层后,苦无目标和呼叫,则电梯处于无方向状态,方向指示灯全灭,否则电梯内某个方向的指示灯亮,表示电梯将向该方向运行。等接到“GO”信号后电梯立即继续运行。若无GO信号,则电梯在等了上下乘客和电梯继续运行时间后也将继续运行。 8. 当一个目标(呼叫)已经被服务后,应将对应的指示灯熄灭。 (三)电梯运行的控制策略 以下是几个候选策略: 1.先来先服务策略: 将所有呼叫和目标按到达时间排队,然后一一完成。这是相当简单的策略,只需要设计一个将呼叫和目标排队的数据结构。因为该策略效率也很低,所以没有实际的电梯采用这种策略。 2. 顺便服务策略: 顺便服务是一种最常见的简单策略。这种策略在运行控制中所规定的安全前提下,一次将一个方向上的所有呼叫和目标全部完成。然后掉转运行方向完成另外一个方向上的所有呼叫和目标。 可以采用设定目标楼层的办法来实现这个策略,即电梯向一个目标楼层运行,但这个楼层可以修改。具体策略如下: 1) 修改目标楼层的策略: a.如果电梯运行方向向上,那么如果新到一个介于当前电梯所处楼层和目标楼层之间,又可以安全到达的向上呼叫或者目标,将目标楼层修改为这个新的楼层。 b.如果电梯运行方向向下,那么如果新到一个介于当前电梯所处楼层和目标楼层之间,又可以安全到达的向下呼叫或者目标,将目标楼层修改为这个新的楼层。 2)确定新的目标楼层: 如果电梯向上运行,当它到达某个目标楼层后,则依照以下顺序确定下一个目标楼层: a.如果比当前层高的楼层有向上呼叫或者目标,那么以最低的高于当前楼层的有向上呼叫或者目标的楼层为目标。 b.如果无法确定目标楼层,那么以最高的向下呼叫或者目标所在楼层为电梯当前目标楼层。 c.如果无法确定目标楼层,那么以最低的向上呼叫所在楼层为电梯当前的目标楼层。 d.如果仍然不能确定目标楼层(此时实际上没有任何呼叫和目标),那么电梯无目标,运行暂停。 如果电梯向下运行,依照以下顺序确定下一目标楼层: a.如果比当前层低的楼层有向下呼叫或者目标,那么以最高的低于当前楼层的有向下呼叫或者目标的楼层为目标。 b.如果无法确定目标楼层,那么以最低的向上呼叫或者目标所在楼层为电梯当前目标楼层。 c.如果无法确定目标楼层,那么以最高的向下呼叫楼层为目标楼层。 d.如果仍然不能确定目标楼层(此时实际上没有任何呼叫和目标),那么电梯无目标,运行暂停。 3)最快响应策略: 响应所有的现在存在的所有呼叫和目标所需时间(采用不同方案电梯停靠时间相同,所以不必考虑)最短的策略。 可选方案一是电梯先向上运行响应经过各层的目标和向上呼叫,再向下运行响应所有向下呼叫以及途经各层的目标,最后再向上响应剩余的向上呼叫。二是恰好相反,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值