[one_demo_15]模擬交通燈管理系統

項目需求

模擬實現十字路口的交通燈管理系統邏輯。

  1. 異步隨機產生各個路線上行走的車輛。例如,由南向北的直行車輛,由南向西的左轉車輛,由南向東的右轉車輛。
  2. 信號燈忽略黃燈,只考慮紅燈和綠燈。
  3. 需考慮左轉車輛受信號燈控制,右轉車輛不受信號燈控制。
  4. 信號燈的具體的控制邏輯與現實中的情況一致,不考慮特殊情況。南北向車輛和東西向車輛交替放行,同方向車輛,先放行直行車輛再放行左轉車輛。
  5. 每輛車過路口的時間爲1秒,可以使用sleep模擬。
  6. 隨機生成車輛時間和交通燈切換時間自定義。

需求分析

爲了便於分析,可以畫十字路口的圖幫助分析。

面向對象分析和設計

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();
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章