交通燈管理系統
面向對象設計思想:
例題:
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正在過馬路!