您的位置:首页 > 职场人生

黑马程序员之交通灯管理系统

2013-06-15 11:30 204 查看
------- android培训java培训、期待与您交流! ----------
由于路只有12个方向,所以需要12个方向的灯来分别控制每一条路:

南北灯(直行),南西灯(左转),南东灯(右转)

北南灯(直行),北东灯(左转),北西灯(右转)

东西灯(直行), 东南灯(左转),东北灯(右转)

西东灯(直行), 西北灯(左转), 西南灯(右转)

1,Road类

Road类有两个成员变量,一个是路名name,一个是车辆集合vehicles

在Road类的构造方法中,利用线程实现随机增加车辆的方法,并且启动定时器,随时判断能够通过路口。

2,Lamp类

利用枚举实现Lamp类,因为路只有12个方向,所以Lamp类的对象只有12个,分别对应12条路。

Lamp类的构造方法,要传入3个参数,分别为对面的灯opposite,下一个要变绿的灯next,还有一个用于判断当前灯红绿的变量lighted。

Lamp类要有判断当前灯是绿还是红的方法isLighted

Lamp类要有设置当前和对面灯为绿灯的方法light

Lamp类要有设置当前和对象灯为红灯的方法lightOut,并且设为红灯后,要把下一个要变绿的灯next变为绿灯,并且把下一个变绿灯的对面的灯也设置为绿灯。

3,LampController类

LampController类是控制系统,控制多长时间变绿或者变红,所以LampController类要有一个定时器进行定时,固定时间使得不同方向的灯交替变绿

学习心得:通过这个小系统,应该学会面向对象的设计方法,即谁拥有数据,谁就对外提供操作这些数据的方法。

典型案例

①人在黑板上画圆,可以抽象为几个对象:人,黑板,圆?那么画圆的动作是哪个对象的方法?画圆需要圆心和半径,那么圆心和半径是谁的数据?是圆,所以画圆的方法应该由圆来提供。

②列车司机紧急刹车:有两个对象列车和司机,刹车的方法是谁提供?很明显是列车,因为列车拥有速度、发动机等数据。

③售票员正在统计售货小票的金额:统计金额的方法由售货小票提供。人只是调用了售货小票的方法。

④人把门关上了:关门的方法由门提供。人只是调用了门的关门方法。

⑤路上有很多汽车,路上还要增加新的汽车,还要随时减少汽车:减少汽车的方法由谁提供?由路提供。

⑥两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子:对象:石头,石刀,树,木材,椅子。石头可以磨成石刀,那么是石头要提供方法把自己变成石刀?错,把自己变成刀,自己都没了。石头并没有石刀的属性,所以不能提供变成石刀的方法。所以定义一个石刀加工厂,KnifeFactory提供生成石刀的方法。石刀又有砍树的方法,返回木材。同理,椅子加工厂chairFactory提供方法,把木材变成椅子。

⑦球从一根绳子的一端移到了另一端:两个对象:小球、绳子。绳子的本质是为球的移动提供了方向,提供球要滚动到哪一点,所以绳子要提供一个方法nextPoint,返回小球要移动的下一个点。小球的构造方法中,把开始的点和绳子对象传给小球,小球还有移动的方法,调用绳子的方法nextPoint。

交通灯的源代码
Lamp类:
package traffic;

public enum 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 boolean lighted;//存储每个Lamp对象中的亮黑状态
private String opposite;//对面的灯
private String next;//下一个要变绿的灯

//	private Lamp(){}

private Lamp(String opposite,String next,boolean lighted){
System.out.println("对面的灯:"+opposite+" 下一个绿灯:"+next+" 亮灭:"+lighted);
this.opposite = opposite;
this.lighted = lighted;
this.next = next;
}

//现在的灯是不是亮的
public boolean isLighted(){
System.out.println(toString()+"是否是绿灯:"+lighted);
return lighted;
}
//亮灯,绿灯
public void light(){
this.lighted=true;
System.out.println(toString() + " lamp is green.下面有6个方向的车通过");
//不进行判断会死循环
if(opposite != null){
//获取对面的灯的对象,使其也变亮
Lamp.valueOf(opposite).light();
}
}
//把当前灯变为红灯,并返回要变绿的灯
public Lamp lightOut(){
this.lighted =false;
if(opposite!=null){
Lamp.valueOf(opposite).lightOut();
}
Lamp nextlamp = null;
if(next!=null){
nextlamp=Lamp.valueOf(next);
nextlamp.light();
System.out.println("绿灯从"+ name()+"---->切换为"+ next);
}
return nextlamp;
}
}


灯控制器:LampController
package traffic;

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();
//每隔10秒当前灯变黑
ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run() {
System.out.println(currentLamp+"即将变为红灯");
currentLamp = currentLamp.lightOut();
}

},
10,
10,
TimeUnit.SECONDS);
}

}

路:Road
package traffic;

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 {
//每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合
private List<String> vehicles = new ArrayList<String>();
private String name = null;

public Road(String name){
this.name = name;
//jdk1.5的线程库Executors
ExecutorService pool = Executors.newSingleThreadExecutor();
//在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车
//Runalbe是接口不能直接new,所以这里new了个接口实现类的对象
pool.execute(new Runnable(){
public void run() {
for(int i= 1;i<1000;i++){
try {
//产生1-10之间的随机整数
Thread.sleep((new Random().nextInt(10)+1)*1000);
System.out.println(Road.this.name+"线程到底是个什么东西");
} catch (InterruptedException e) {
e.printStackTrace();
}
//内部类想要访问外部类的局部变量,外部类的局部变量要加上final修饰
//这里也可以访问外部类的成员变量来实现
//访问外部类的成员变量本来可以直接写外部类的成员变量名,
//但是如果这个变量与自己类里的变量名冲突了,要加上类名.this.变量名
vehicles.add(Road.this.name + "_" + i);
System.out.println("牌照为"+Road.this.name + "_" + i + "的车来了");
}

}

});

//在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则将集合中的第一辆车移除掉
ScheduledExecutorService  timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){

public void run() {
if(vehicles.size() > 0){
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
//布尔型的变量直接用,不用和true去比较了lighted==true
if(lighted){
System.out.println(vehicles.remove(0)+"开走了!");
}
}
}

},
1,
1,
TimeUnit.SECONDS);

}
}


主程序:
package traffic;

public class MainClass {

public static void main(String[] args) {
//创建12条路的对象
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 LampController();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: