項目需求
模擬實現十字路口的交通燈管理系統邏輯。
- 異步隨機產生各個路線上行走的車輛。例如,由南向北的直行車輛,由南向西的左轉車輛,由南向東的右轉車輛。
- 信號燈忽略黃燈,只考慮紅燈和綠燈。
- 需考慮左轉車輛受信號燈控制,右轉車輛不受信號燈控制。
- 信號燈的具體的控制邏輯與現實中的情況一致,不考慮特殊情況。南北向車輛和東西向車輛交替放行,同方向車輛,先放行直行車輛再放行左轉車輛。
- 每輛車過路口的時間爲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();
}
}