交通燈管理系統
一、需求分析。
在進行設計之前我們需要了解具體的十字路口交通規則:1、紅燈停綠燈行。2、對於十字路口的四個路口而言,“向右轉彎”始終是允許的即該方向始終保持綠燈。3、在十字路口處可以有12條行車路線可以選擇(如下圖所示),其中可以分爲5組,每一組中的一條路線是可行的則表示改組中的其他路線也是可行的。
二、系統設計。
1、 對象分析:系統中可以抽象出的對象爲:路、紅綠燈和燈控制系統。(在面向對象的分析過程中擁有數據的對象提供操作數據的方法)
2、 對象設計:
1) 路:
每條路線上會出現多輛車,路就是一個集合,路線上要隨機增加新的車,當在燈綠期間車通過路口需要一秒,即路集合中每秒減少一輛車,並返回減少車的名字。使用Road類表示路線,每個Road對象代表一個路線,前面已經分析了需要12條路線,即系統中要產生12個Road實例對象。
2) 紅綠燈:
每條路線每隔一秒都會檢查控制本路線的燈是否爲綠,一個燈由綠變紅時,應該將下一個方向的燈變綠。設計一個Lamp類來表示一個交通燈,每個交通燈都維護一個狀態:亮(綠),不亮(紅),每個交通燈要有變亮和變不亮的方法,並且能返回自己的狀態。
總共有12條路線,所以,系統中總共要產生12個交通燈。右拐彎的路線本來不受燈的控制,但是爲了讓程序採用統一的處理方式,故假設出有四個右拐彎的燈,只是這些燈爲常亮狀態。除了右拐彎方向的其他8條路線的燈,它們是兩兩成對的,可以歸爲4組,所以,在編程處理時,只要從這4組中各取出一個燈,對這4個燈依次變亮,與這4個燈方向對應的燈則隨之一同變化,因此Lamp類中要有一個變量來記住自己相反方向的燈對象,在一個Lamp對象的變亮和變黑方法中,將對應方向的燈也變亮和變黑。每個燈變黑時,都伴隨者下一個燈的變亮,Lamp類中還應該有一個變量來記住自己的下一個燈對象。
無論在程序的什麼地方去獲得某個方向的燈時,每次獲得的都是同一個實例對象,所以Lamp類改用枚舉來做顯然具有很大的方便性,永遠都只有代表12個方向的燈的實例對象。
3) 燈控制系統:設計一個LampController類,它定時讓當前的綠燈變紅。
三、系統實現。
1、 Road類設計與實現。
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>vehicles = newArrayList<String>();
//定義一個變量存儲路線名
private Stringname = null;
public Road(String name){
this.name = name;
//模擬車上路的情況,假設該路線上有99輛車
ExecutorServicepool = Executors.newSingleThreadExecutor();
pool.execute(new Runnable() {
@Override
public void run() {
//通過線程控制實現,路線每隔1-10秒增加一輛車
for (int i = 0; i < 100; i++) {
try {
Thread.sleep((new Random().nextInt(10)+1)*1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
vehicles.add(Road.this.name +"_" + i);
}
}
});
//每隔一秒檢查對應的燈是否爲綠,如果是綠的就輸出集合第一個,即第一輛車
ScheduledExecutorServicetimer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable() {
@Override
publicvoid run() {
if (vehicles.size()>0) {
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
if (lighted) {
System.out.println(vehicles.remove(0) +"is traversing !");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
2、 Lamp類的設計與實現。
publicenum 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 boolean lighted;
//同屬於一個分組的路線
private Stringopposite;
//不同屬於一個分組的下一個路線
private Stringnext;
/*
* 功能:判斷燈的狀態
* 參數:無
* 返回值:燈的狀態(true表示綠燈亮 false表示紅燈亮)
*/
public boolean isLighted(){
return lighted;
}
/*
* 功能:將本路線的燈設爲綠燈狀態,同時將該路線的小組的燈設爲綠燈狀態
* 參數:無
* 返回值:無
*/
public void light(){
this.lighted =true;
if(opposite !=null){
Lamp.valueOf(opposite).light();
}
System.out.println(name() +" lamp is green,下面總共應該有6個方向能看到汽車穿過!");
}
//某個燈變紅時,對應燈也要變紅,並且下一個方向的燈要變綠
public Lamp blackOut(){
this.lighted =false;
if(opposite !=null){
Lamp.valueOf(opposite).blackOut();
}
Lamp nextLamp= null;
if(next !=null){
nextLamp = Lamp.valueOf(next);
System.out.println("綠燈從" + name()+"-------->切換爲" +next);
nextLamp.light();
}
//返回下一個燈變綠
return nextLamp;
}
}
3、 LampController 類的設計與實現。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LampControl {
private LampcurrentLamp;
public LampControl(){
//剛開始讓由南向北的燈變綠;
currentLamp = Lamp.S2N;
currentLamp.light();
//10秒燈的轉換時間
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
@Override
publicvoid run() {
// 設定定時器
currentLamp =currentLamp.blackOut();
}},
10,
10,
TimeUnit.SECONDS);
}
}
四、測試類。
public class TestClass {
/**
* 該類主要用於測試
*/
public static void main(String[] args) {
//定義一個數組存儲十字路口的各個路線名
String[] directions = new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S" };
for(int i=0;i<directions.length;i++){
new Road(directions[i]);
}
new LampControl();
}
}
輸出結果:
N2S lamp is green,下面總共應該有6個方向能看到汽車穿過!
S2N lamp is green,下面總共應該有6個方向能看到汽車穿過!
W2S_0 is traversing !
N2S_0 is traversing !
N2W_0 is traversing !
S2N_0 is traversing !
S2E_0 is traversing !
E2N_0 is traversing !
綠燈從S2N-------->切換爲S2W
N2E lamp is green,下面總共應該有6個方向能看到汽車穿過!
S2W lamp is green,下面總共應該有6個方向能看到汽車穿過!
S2W_0 is traversing !
N2E_0 is traversing !
S2W_1 is traversing !
W2S_1 is traversing !
S2W_2 is traversing !
E2N_1 is traversing !
N2W_1 is traversing !
N2E_1 is traversing !
S2W_3 is traversing !
E2N_2 is traversing !
S2E_1 is traversing !
W2S_2 is traversing !
N2E_2 is traversing !
N2W_2 is traversing !
綠燈從S2W-------->切換爲E2W
W2E lamp is green,下面總共應該有6個方向能看到汽車穿過!
E2W lamp is green,下面總共應該有6個方向能看到汽車穿過!
E2W_0 is traversing !
W2E_0 is traversing !
E2W_1 is traversing !
W2E_1 is traversing !
E2W_2 is traversing !
W2E_2 is traversing !
·······