您的位置:首页 > 编程语言 > Java开发

JAVA第二十五弹(交通灯管理系统)

2013-08-24 00:20 691 查看
----------------------android培训java培训期待与您交流! ----------------------

JAVA第二十五弹(交通灯管理系统)

——————(个人见解,有错误的地方欢迎批评指正)—————

(如有雷同纯属巧合)

模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:

Ø 异步随机生成按照各个路线行驶的车辆。

例如:

由南向而来去往北向的车辆 ---- 直行车辆

由西向而来去往南向的车辆 ---- 右转车辆

由东向而来去往南向的车辆 ---- 左转车辆

……

Ø 信号灯忽略黄灯,只考虑红灯和绿灯。

Ø 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。

Ø 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。

注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。

Ø 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。

Ø 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。

Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

需求分析:

首先按照一般的思维进行分析,该需求有车辆,红绿灯。它们之间有什么联系呢?车辆要行驶是受什么控制?按照一般的思维,车辆行驶是看红绿灯的,绿灯亮,则车辆可以行驶,红灯亮,则汽车等绿灯亮。既然车辆是看红绿灯行驶,那么红绿灯就控制的车辆的行驶,如何设计红绿灯?红绿灯接受车辆这个对象,如何处理?红绿灯怎么知道车辆要去哪里,它怎么放行车辆?好吧,给每辆车标记它行驶的路线,问题就产生了,有千千万万的车要去各个地方,给每辆车都标记?这显然不合理。

按照上面的思维分析显然就不太合理,实现起来太复杂,那么就要重新思考车辆与红绿灯之间的关系。既然红绿灯不知道车辆去哪里,车辆给自己标上自己要去哪里的的标识又太复杂,那么谁最清楚车辆要去哪里呢?这就引出了另外一个对象→道路。只有道路最清楚车辆要去哪里,因为一条路也就才两个方向,而一个十字路也才12个方向(当然,不考虑飞天遁地的情况),通过道路这个对象来处理车辆与红绿灯的关系,现在它们之间又是一个什么样的关系呢?车辆行驶在道路上,道路分为12个方向,红绿灯控制道路的12个方向的闭合,车辆根据道路的12个方向的闭合来行驶,而不用去考虑每辆车是否去哪里。通过这么设计,这个程序的架构就出来了。这样设计明显比之前来的简单多了,所以说,面向对象就是把复杂的问题简单化。

下面是对车辆行驶路线进行图例分析:



既然道路是衔接车辆和红绿灯的桥梁,那么就先设计道路类,这个道路类要做些什么事呢?首先车辆是行驶在道路上的,所以道路要接收车辆这个对象,因为这是一个模拟程序,所以不用考虑特殊车辆的特殊处理,所有车辆都视为是同一类的车,那么直接就可以内部生成车辆这个对象。因为车辆有新来的和离开的,所以用一个集合先把新生成的车辆存储起来,离开的车辆就把该车辆从集合中删除,生成车辆和移除车辆要实现异步,就要用到多线程,生成车辆一个线程,移除车辆一个线程。那么怎么移除车辆呢?而车辆是否允许通过该路线,就要判断该路线上的红绿灯是否变绿,那么道路的构造函数就应该接受控制该路线的红绿灯对象,通过该红绿灯对象判断该线路上是红灯还是绿灯来进行道路的闭合。通过对道路的分析,那么道路对象就基本设计出来了,如下:

public class Road{
private List<String> transports = new ArrayList<String>();
private //红绿灯成员变量
Road(/*接收一个红绿灯对象*/){
//初始化
ExecutorService executor =
Executors.newSingleThreadExecutor();
executor.execute(new Runnable(){
public void run(){
while(true){
//添加该线路上的车辆
}
}
});

ScheduledExecutorService executor1 =
Executors.newScheduledThreadPool(1);
executor1.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(transports.size()>0){
//得到该红绿灯的状态,每一秒时间判断一次该路线是否为绿灯,
//假如是绿灯则开始删除该路线上的车辆
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}


路和车都设计完了,接下来就要设计红绿灯了,通过之前的图例分析,每条路线会对应一个红绿灯,有12条路线,那么就要12个红绿灯。现在来想想,有12条路,每条路要对应一个红绿灯,而这12个红绿灯彼此之间联系将会非常紧密,因为这个十字路口任何情况下会有6个方向的路要通车,其中4个右转向的路线任何情况下都能通车,这代表这4条路的红绿灯一直是绿的,另外两条路线是另外8条路线中两两对应的路线,例如:南往北的绿灯亮了,那么北往南的绿灯也应该是亮的。因此要控制8个红绿灯,另外4个右转灯不需要控制。因此创建12个对应路线的红绿灯类?那么每个路线的灯有哪些成员和要做那些事?每个红绿灯有红和绿的属性,还应该知道自己对应的是那方向的灯和自己这个灯变红后下一个绿的是那方向的灯,而提供给道路的是自己当前的状态。既然每个灯彼此之间的联系这么紧密,何不使用枚举?日后别人维护时候也不至于晕菜。现在思路理清了就开始设计红绿灯,既然是枚举,那么构造函数初始化时候每个灯应该知道自己路线的灯和其它灯之间的关系,是对应的还是对立的。南往北的灯和北往南的灯是对应的,也就是说南往北的灯绿了,那么北往南的灯也应该是绿的;而当自己变红灯后,应该让自己对立的下一个灯变绿。4个方向右转的灯和其它灯没有直接的联系,所以设为永远是亮的。设计如下:

public enum Lamp {
S2N("N2S","S2W",false),S2W("N2E","E2W",false),
  	E2W("W2E","E2S",false),E2S("W2N","S2N",false),
N2S(null,null,false),N2E(null,null,false),
  	W2E(null,null,false),W2N(null,null,false),
S2E(null,null,true),E2N(null,null,true),
  	N2W(null,null,true),W2S(null,null,true);

private Lamp(String opposite,String next,boolean lighted){
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
private String next;
private String opposite;
private boolean lighted;

public void light(){
this.lighted = true;
if(opposite!= null){
Lamp.valueOf(opposite).lighted = true;
}
}
public Lamp lightOff(){
this.lighted = false;
if(opposite!= null){
Lamp.valueOf(opposite).lighted = false;
}
Lamp nextLight =null;
if(next!=null){
nextLight=Lamp.valueOf(next);
nextLight.light();
}
return nextLight;
}
public boolean isLighted(){
return lighted;
}
}


灯设计好了,就可以补足之前设计道路时空下的代码了,如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Road {
private List<String> transports = new ArrayList<String>();
private String name;

public Road(String name){
this.name = name;
ExecutorService executor =
Executors.newSingleThreadExecutor();
executor.execute(new Runnable(){
public void run(){
for(int i = 1;i<30;i++){
try {
Thread.sleep(
  						(new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
transports.add(
retDirection(Road.this.name)+"第"+i+"辆车");
}
}
});

ScheduledExecutorService executor1 =
Executors.newScheduledThreadPool(1);
executor1.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(transports.size()>0){
boolean lighted = 								                      		Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println(
transports.remove(0)+"开走了!");
}
}
}
},
1,
1,
TimeUnit.SECONDS);

}
private String retDirection(String name){
Lamp lampName = Lamp.valueOf(name);
switch(lampName){
case S2N :
return "南→→北";
case N2S :
return "北→→南";
case E2W :
return "东→→西";
case W2E :
return "西→→东";
case S2W :
return "南→→西";
case N2E :
return "北→→东";
case E2S :
return "东→→南";
case W2N :
return "西→→北";
case S2E :
return "南→→东";
case E2N :
return "东→→北";
case N2W :
return "北→→西";
case W2S :
return "西→→南";
}
return null;
}
}

现在道路和红绿灯都做完了,最后再做个控制系统用来控制红绿灯的开关就可以了,如下:

  import java.util.concurrent.Executors;
  import java.util.concurrent.ScheduledExecutorService;
  import java.util.concurrent.TimeUnit;
  
  
  public class LampControl {
  	private Lamp controlLamp;
  
  	public LampControl(){
  		controlLamp =Lamp.S2N;
  		controlLamp.light();
  
  		ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
  		service.scheduleAtFixedRate(
  			new Runnable(){
  				public void run(){
  					controlLamp = controlLamp.lightOff();
  				}
  			},
  			30,
  			30,
  			TimeUnit.SECONDS);
  	}
  }


到现在,交通灯系统就完成了,最后写个测试类:

public class TheText {

public static void main(String[] args) {
String[] lamps = {"S2W","S2N","E2W","E2S",
"N2S","N2E","W2E","W2N",
"S2E","E2N","N2W","W2S"};
for(String lamp : lamps){
new Road(lamp);
}
new LampControl();
}
}


程序运行结果为:



----------------------android培训java培训期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: