电梯系统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) {}
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值