项目需求
模拟实现十字路口的交通灯管理系统逻辑。
- 异步随机产生各个路线上行走的车辆。例如,由南向北的直行车辆,由南向西的左转车辆,由南向东的右转车辆。
- 信号灯忽略黄灯,只考虑红灯和绿灯。
- 需考虑左转车辆受信号灯控制,右转车辆不受信号灯控制。
- 信号灯的具体的控制逻辑与现实中的情况一致,不考虑特殊情况。南北向车辆和东西向车辆交替放行,同方向车辆,先放行直行车辆再放行左转车辆。
- 每辆车过路口的时间为1秒,可以使用sleep模拟。
- 随机生成车辆时间和交通灯切换时间自定义。
需求分析
为了便于分析,可以画十字路口的图帮助分析。
面向对象分析和设计
1,分析十字路口图,两条路,4个大方向,每个大方向产生3个细分方向,一共有12个方向,那么就需要12个灯。车辆在线路上行驶,车辆的产生和通过由线路控制。
2,系统涉及到3个类,交通灯,线路,交通灯管理器。
3,线路类,12个方向,需要12个线路对象,每个线路对象有一个name表示这个线路的方向,由于车辆不需要考察车的属性和车本身的方法,所以,线路中的车以字符串表示,车的增加和通过路口就使用一个集合模拟队列的先进先出实现。每条线路每隔一秒检查本线路的灯是否为绿,如果绿灯,则将线路车辆集合中的第一辆放行过路口。
4,交通灯类,一共有12个灯是固定的,采用枚举类型比较方便,12个方向的灯,枚举类型设置判断灯是否绿的方法,将红灯转绿灯的方法,将绿转为红灯的方法,本灯下个灯的方法和设置每个枚举属性值的构造方法。对于12个方向灯,分析其特点,其中4个右转的方向是不受灯控制的,为了便于编程,将这个4个灯设置为常绿;另外8组方向,当一个方向绿时,其反方向必然也为绿,可以将这8组,看作两个4组,其中一组受到另外一组的控制,需要一个反方向变量来表示器反方向,拿出来其中的一个4组方向,定时对这4个方向做轮询,比如一个方向变红后,那么其下一个方向就变绿,并且返回这个变绿的方向以便操作。
5,交通灯管理器类,整个系统中只有一个交通灯管理器,这个类要设计为单例。交通灯管理器启动一个计划线程,每隔10秒将一个灯变红,并将下一个灯变绿。
6,main类,测试类,for循环出12条路线。创建一个交通灯管理器,启动其start方法。
类图设计
Road
属性,name;//表示方向,可以使用Lamp的枚举,vehicles;//车辆的集合
方法,在构造方法中,启动一个线程,每个一段随机时间就向车辆集合中增加一辆车;启动一个定时器,每个1秒,就检查该方向的灯是否为绿,绿就打印车辆集合中的第一辆车通过的信息并remove它。
Lamp
属性,12个方向,定义好其对面方向,灯绿否和下个方向;等的状态,isGreen;相反方向的灯,oppositeLampName;下一个灯,nextLampName;由于要在构造方法中定义一个方向的状态,反方向灯和下一个灯,但是枚举中无法在枚举定义之前引用这个枚举,所以使用字符串表示反方向灯和下一个灯。
方法,toGreen();toRed();,变灯,这两个方法中要让向反方向的灯也随之变化。toRed()方法中还要将下个灯变绿。
LampController
整个系统只有一个管理器,所以这个类设计为单例。在构造方法中需要将第一个灯设置为绿。
方法,start();这个方法中创建一个定时器,每隔10秒将当前灯变红,将下个灯变绿。
MainClass
for循环12条线路,创建一个LampController对象,并调用start()方法。
java实现
/**
* 路线类
* @author Administrator
*
*/
public class Road {
private String name;//路线的名字
private List<String> vehicles = new ArrayList<String>();//车辆名字
/*
* 构造方法中获取路线名字和创建线程判断路灯给车辆放行,创建线程随机增加车辆
*/
public Road(String name){
this.name = name;
//创建线程判断路灯,是否放行车辆,也可以同时定时器线程实现
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
while(true){
//获取本线路的路灯
boolean isGreen = Lamp.valueOf(Road.this.name).isGreen();
//判断路灯
if(isGreen){
if(vehicles.size() > 0){
//车辆通过路口的时间为一秒
try {
Thread.sleep(1000);
System.out.println(Road.this.name + ":" + vehicles.remove(0) + "通过路口");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
});
//创建线程随机增加车辆
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
//一共增加100两车上路
for(int i = 0; i < 1000; i++){
//利用随机数每个1-5秒出现一辆车上路
int interval = new Random().nextInt(4) + 1;
try {
Thread.sleep(interval * 1000);
//将车辆放入队列
vehicles.add("车辆_" + i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
}
/**
* 交通灯枚举
* @author Administrator
* S2N,S2W,E2W,E2S,
N2S,N2E,W2E,W3N,
S2E,N2W,W2S,E2N;
*/
public enum Lamp {
//十二个路线
S2N("N2S", false, "S2W"),S2W("N2E", false, "E2W"),E2W("W2E", false,"E2S"),E2S("W2N", false, "S2N"),
N2S(null, false, null),N2E(null, false, null),W2E(null, false, null),W2N(null, false, null),
S2E(null, true, null),N2W(null, true, null),W2S(null, true, null),E2N(null, true, null);
private boolean isGreen = false;//是否为绿
private String nextLamp;//下一个变色的灯
private String oppositeLamp;//对面的灯
/*
* 构造方法提供对面灯,颜色,下个灯这个三个属性
* 创建定时器,每隔10秒变灯
*/
private Lamp(String oppositeLamp, boolean isGreen, String nextLamp){
this.nextLamp = nextLamp;
this.oppositeLamp = oppositeLamp;
this.isGreen = isGreen;
}
/**
* 获取灯的颜色
*/
public boolean isGreen(){
return this.isGreen;
}
/**
* 变绿
*/
public void toGreen(){
//本灯变绿
this.isGreen = true;
//对面灯变绿
Lamp.valueOf(this.oppositeLamp).isGreen = true;
}
/**
* 变红
*/
public Lamp toRed(){
//本灯变红
this.isGreen = false;
//对面的灯也变红
Lamp.valueOf(this.oppositeLamp).isGreen = false;
//获取下个灯
Lamp next = Lamp.valueOf(this.nextLamp);
//下个灯绿
if(next != null){
next.toGreen();
}
//返回下个灯
return next;
}
}
/**
* 交通灯管理类
* @author Administrator
*
*/
public class LampManager {
//定义一个当前灯的属性
Lamp currentLamp = Lamp.S2N;
//全局只有一个交通灯,所以这个类设计为单例
private LampManager(){}
//创建一个懒汉单例
private static LampManager lampManager = new LampManager();
//获取这个单例
public static LampManager getLazyInstance(){
return lampManager;
}
//设计一个定时器,每隔10秒变灯
public void start(){
//起初,将当前灯变绿
currentLamp.toGreen();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
public void run() {
currentLamp = currentLamp.toRed();
System.out.println(currentLamp + "灯变绿了");
}
},
0,
10,
TimeUnit.SECONDS
);
}
}
/**
* 测试方法
* @author Administrator
*
*/
public class MainClass {
public static void main(String[] args) {
//for12条线路
Lamp[] lamps = Lamp.values();
for(Lamp lamp:lamps){
String name = lamp.name();
Road road = new Road(name);
System.out.println(name + "开通了");
}
//创建一个交通灯管理器
LampManager lampManager = LampManager.getLazyInstance();
//开启对交通灯的管理
lampManager.start();
}
}