交通燈管理系統

交通燈管理系統

面向對象設計思想:

例題:

1,  兩塊石頭磨成一把石刀,石刀可以砍樹,砍成木材,木材做成椅子

用面向對象的思想模擬

如下:

對象有:

           石頭:Stone

           石刀:StoneKnife

           木材:Wood

           椅子:Chair

                   兩塊石頭磨成一把刀,則就是一個工廠類,傳入兩塊石頭做參數,返回一把石刀

        StoneKnifeFactory

           木材做成椅子也是一個工廠類,將木材作爲參數,返回一把椅子

ChairFactory

代碼如下:

StoneKnife

public class StoneKnife {

	private Stone s1;
	private Stone s2;

	// 石刀由兩塊石頭磨成
	public StoneKnife(Stone s1, Stone s2) {
		this.s1 = s1;
		this.s2 = s2;
	}

	// 石刀有砍樹的功能
	public Wood cutTree() {
		return new Wood();
	}
}

Chair

public class Chair {

	// 椅子由木材做成
	private Wood w;
	public Chair(Wood w) {
		this.w = w;
	}
}
    StoneKnifeFactory

public class StoneKnifeFactory {

	public static StoneKnife creatStoneKnife(Stone s1,Stone s2){
		return new StoneKnife(s1,s2);
	}
}
ChairFactory

public class ChairFactory {

	public static Chair creatChair(Wood w){
		return new Chair(w);
	}
}

模擬流程:


public class TestDemo {

	public static void main(String[] args) {
		// 創建兩塊石頭
		Stone s1 = new Stone();
		Stone s2 = new Stone();
		// 將兩塊石頭磨成一把石刀
		StoneKnife sk = StoneKnifeFactory.creatStoneKnife(s1, s2);
		// 砍一塊木材
		Wood w = sk.cutTree();
		// 將木材做成椅子
		Chair chair = ChairFactory.creatChair(w);
	}
}


2,  球從一根繩子的一端移動到了另一端

兩個對象:    球Ball

每個球都應該有一個繩子來指引移動的方向,有一個起始位置,有一個移動的方法,就是從一點到另一點,調用繩子的方法

public class Rope {

	// 繩子的兩個端點,一個代表起點,一個代表終點
	private Point start;
	private Point end;

	public Rope(Point start, Point end) {
		this.start = start;
		this.end = end;
	}

	// 從一個點到另一個點
	public Point nextPoint(Point point) {
		// 應根據傳進來的點,返回指定的點
		return new Point();
	}
}

繩子 Rope

爲球的移動提供方向,兩個屬性,起始點和終點,有一個方法,獲取下一個點

public class Ball {

	// 爲每個球指定一個繩子
	private Rope rope;
	// 每個球都有起始位置
	private Point currentPoint;

	public Ball(Rope rope, Point currentPoint) {
		this.rope = rope;
		this.currentPoint = currentPoint;
	}

	// 球移動的方法,從繩子一端移動到另一端
	public void move() {
		// 移動到了currentPoint點
		currentPoint = rope.nextPoint(currentPoint);
		System.out.println("小球移動到了" + currentPoint);
	}
}

交通燈思路:

已知一共有12條路線,右轉4條,左轉4條,直行4條

         右轉不受交通燈控制,視爲常綠

         現在考慮8條路線,因爲來往是對稱的,所以只用考慮4條路線

分別是

按紅,黃,藍,綠,的順序

         紅:SàN直行,該路上綠燈,其它都是紅燈

         黃:直行結束後,黃:SàW左轉,該路上左轉燈亮綠燈

         藍:豎着的路行駛結束後,換橫着的馬路,EàW,

         綠:直行結束,再接着該路上左轉,EàS

 

由上可知,4條路線輪流變換紅綠燈行駛

 

交通燈:

         使用枚舉類,

         總共有12條路線,對應的就有12個燈

         實際上只需要考慮4個燈輪流交換

 

交通燈有3個成員變量

一個boolean類型記錄自己的狀態,是紅燈還是綠燈亮

一個String類型變量記錄對應方向燈的狀態

一個String類型變量記錄下一個燈

 

兩個方法,一個是點亮綠燈

                     一個是綠燈變紅燈

//總共12個燈,定義枚舉,指定12個Lamp元素即可
public enum Lamp {
	
	// 使用String類型變量來封裝枚舉名,並在初始化中使用,可以避免非法向前引用的問題
	S2N("N2S", false, "S2W"), // 1,豎着的馬路,向上直行
	S2W("N2E", false, "E2W"), // 2,豎着的馬路,左轉彎
	E2W("W2E", false, "E2S"), // 3,橫着的馬路,直行
	E2S("W2N", false, "S2N"), // 4,橫着的馬路,左轉彎
	/* 右轉路線,燈爲常綠 */
	S2E(null, true, null), E2N(null, true, null), N2W(null, true, null), W2S(
			null, true, null),
	/* 對應方向的燈,不需要進行邏輯考慮,只需遵守上面4個燈的規則就行 */
	N2S(null, false, null), N2E(null, false, null), W2E(null, false, null), W2N(
			null, false, null);
	// 記錄當前狀態
	private boolean lighted;
	// 與燈同時爲綠的對應方向的燈,保存的是燈的名字,後面可以根據燈的名字獲取對應的實例對象
	private String opposite;
	// 燈變紅時,下一個變綠的燈
	private String next;

	// 初始化燈,枚舉的構造方法必須是私有
	private Lamp(String oppsite, boolean lighted, String next) {
		this.opposite = oppsite;
		this.lighted = lighted;
		this.next = next;
	}

	// 判斷當前燈是否是亮的
	public boolean isLighted() {
		return lighted;
	}

	// 當前燈變綠,隨之要將對應的燈也變綠
	public void light() {
		this.lighted = true;
		// 調用自己方法,將對應的燈也變綠,通過燈名獲取對應燈的實例對象
		if (opposite != null) {
			Lamp opp = Lamp.valueOf(opposite);
			opp.light();
			System.out.println("當前綠的燈是"+name()+"和"+opposite+"還有右轉彎一共6個綠燈");
		}
	}

	// 當前燈變紅,同時返回下一個變綠的燈
	public Lamp blackOut() {
		this.lighted = false;
		// 將對應方向的燈也變紅
		if (opposite != null) {
			Lamp.valueOf(opposite).blackOut();
		}
		// 獲得下一個綠燈,並返回
		Lamp nextLamp = null;
		if (next != null) {
			nextLamp = Lamp.valueOf(next);
			// 將下一個燈變綠
			nextLamp.light();
			System.out.println(name()+"和"+opposite+"變紅了,"+next+"燈綠了");
		}
		return nextLamp;
	}
}

交通燈的控制器

一個成員變量,用來記錄當前的燈

 

一個方法,定義一個計時器,每過10秒,將當前燈變紅,並獲取下一個變綠的燈

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

//燈的控制器
public class LampController {

	// 當前亮的燈
	private Lamp currentLamp;

	public LampController() {
		// 指定第一個亮的燈
		currentLamp = Lamp.S2N;
		// 將該燈變綠
		currentLamp.light();

		// 定義一個計時器,每隔指定時間就將當前燈變紅,並將下一個燈變綠
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		// 按照指定頻率執行線程中的方法中的代碼
		timer.scheduleAtFixedRate(new Runnable() {
			// run方法中是指定的要執行的代碼
			public void run() {
				// 將當前燈變黑,同時將當前燈指向下一個變綠的燈
				currentLamp = currentLamp.blackOut();
			}
		}, 10, 10, TimeUnit.SECONDS);
	}
}


Road類,描述公路

定義一個集合,封裝String類型數據,來代表車輛

一共有12條路線,所以每創建一條路線都給該路線指定對應的名字

 

單獨封裝一個線程來模擬路上來的車輛,即每條路上隨機增加的車輛

 

再單獨封裝一個線程來模擬過馬路的車輛,即路上減少的車輛

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 {

	// 定義集合存儲車輛
	List<String> vehicles = new ArrayList<String>();
	// 每條路都有自己的名字,根據該名字也可以獲得該路上對應的燈
	private String name;

	public Road(String name) {
		this.name = name;

		// 獲得線程池中的一個線程,來向路上添加車輛
		ExecutorService pool = Executors.newSingleThreadExecutor();
		// new一個Runnable對象,往裏面封裝添加車輛的代碼
		pool.execute(new Runnable() {
			public void run() {

				for (int i = 1; i <= 1000; i++) {
					// 每隔1——10秒就添加一輛車輛
					try {
						Thread.sleep((new Random().nextInt(10) + 1) * 1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vehicles.add(Road.this.name + "_" + i);
				}
			}
		});

		// 下面定義方法減少車輛,即車輛穿過路口,也是單獨封裝到 一個線程中去
		// 定義一個線程調度池
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);

		// 按固定頻率執行線程中的代碼,延遲1s執行,之後過1s再執行該代碼
		timer.scheduleAtFixedRate(new Runnable() {
			public void run() {
				// 有車輛才運行
				if (vehicles.size() > 0) {
					// 根據路名獲取路燈
					Lamp lamp = Lamp.valueOf(Road.this.name);
					// 如果是綠燈亮
					if (lamp.isLighted()) {
						System.out.println(vehicles.remove(0) + "正在過馬路!");
					}
				}
			}
		}, 1, 1, TimeUnit.SECONDS);
	}
}

場景類:

public class MainClass {

	public static void main(String[] args) {

		// 將12條路線都創建出來
		String[] directors = { "S2N", "S2W", "E2W", "E2S", "S2E", "E2N", "N2W",
				"W2S", "N2S", "N2E", "W2E", "W2N" };
		for (String director : directors) {
			new Road(director);
		}
		new LampController();
	}
}

運行結果:

當前綠的燈是S2N和N2S還有右轉彎一共6個綠燈
S2N_1正在過馬路!
S2E_1正在過馬路!
W2S_1正在過馬路!
S2N_2正在過馬路!
N2W_1正在過馬路!
S2E_2正在過馬路!
E2N_1正在過馬路!
E2N_2正在過馬路!
W2S_2正在過馬路!
N2S_1正在過馬路!
當前綠的燈是S2W和N2E還有右轉彎一共6個綠燈
S2N和N2S變紅了,S2W燈綠了
S2W_1正在過馬路!
N2E_1正在過馬路!
S2W_2正在過馬路!
N2E_2正在過馬路!
S2W_3正在過馬路!
E2N_3正在過馬路!
S2W_4正在過馬路!
N2W_2正在過馬路!
E2N_4正在過馬路!
N2E_3正在過馬路!
W2S_3正在過馬路!
S2E_3正在過馬路!
當前綠的燈是E2W和W2E還有右轉彎一共6個綠燈
S2W和N2E變紅了,E2W燈綠了
E2W_1正在過馬路!
N2W_3正在過馬路!
W2E_1正在過馬路!
E2W_2正在過馬路!
E2N_5正在過馬路!
W2E_2正在過馬路!
E2W_3正在過馬路!
E2W_4正在過馬路!
W2S_4正在過馬路!
W2E_3正在過馬路!
N2W_4正在過馬路!

發佈了49 篇原創文章 · 獲贊 12 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章