---------------------- android培训,java培训、期待与您交流! ----------------------
交通灯:
根据现实生活中的交通灯分析,交通灯的路线可以分为12条,这12条路线可以分成相同的4组, 每一组中的路线分别是: 直行 ,左转 , 和右转. 面对面的交通灯的亮灯规则相同 , 也就是说: 南面直行的灯变绿灯, 北面直行的也是绿灯 ; 当直行结束之后 , 南北左转灯变绿灯, 南北的绿灯结束后 , 东西面按照相同的规则执行. 值得注意的是,交通灯中,没有右转灯,所以可以假设右转是常绿灯.
规则简单介绍:
1. 南北直行
2. 南北左转
3. 东西直行
4. 东西左转
面向对象分析:
在交通灯这道题中涉及到灯, 灯的控制器, 路线, 车辆. 灯有红, 绿, 黄三种颜色; 灯的控制器控制颜色的改变; 路线有直行,左转,右转三种情况; 因为这题不需要考虑车辆通过红绿灯的过程,只需要知道有一辆车通过了,并且车辆是在路线上通行的,所以车辆不是对象, 而是路线中的一部分. 但是需要注意的是, 当绿灯亮起的时候, 并不是所有的车都可以通行, 而是只有最前面的那一辆才能通行, 而且车是有增有减的, 所以应该定义一个集合来存储车辆
设计思路:
灯:
总共有12盏灯,并且这12盏灯是固定不变的,每一盏灯都是一个对象,并且每一盏灯都要有一个状态”红或者绿”, 并且每个灯都要有一个变红和变绿的方法. 所以应该把灯用枚举来表示.
虽然有12盏灯, 显得很多, 但是其实只有4盏灯是有逻辑的, 可以选择南à北;
南à西 ; 西à东 ; 西à北来作为这4盏灯,与之相对的4盏灯的状态和这4盏灯的是一致的. 还有4盏灯是右转的, 实际生活中没有右转灯, 所以这4盏右转灯可以假定为常绿灯.
灯的类中只有三个属性 : boolean lighted---(是否是绿灯) , String opposite---(与之相反的灯) , String next ---(下一盏灯)
灯只有两个方法: void light()---点亮自己这盏灯和与之对应的反方向的灯 ,
Lamp nextLamp()---当本身变成红灯的时候,把与之对应的灯变红,并且把下一盏灯变绿
publicenum Lamp {
/* 4盏有逻辑的灯(opposite和next要是String类型,因为如果是Lamp类型,
那么在调用的时候,opposite和next对象还没有创建,在使用到的时候通过枚举的valueOf方法把字符串转换成相应的Lamp类型)*/
S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","S2N"),
//4盏与之对应的灯(这里的opposite和next为空是因为这样做就保证light()方法和blackOut()不会变成死循环)
N2S(false,"null","null"),N2E(false,"null","null"),W2E(false,"null","null"),W2N(false,"null","null"),
//4盏右转的灯
S2E(true,"null","null"),E2N(true,"null","null"),N2W(true,"null","null"),W2S(true,"null","null");
//当前是否绿灯
privatebooleanlighting;
//对应的灯的名字
private String opposite;
//下一盏灯的名字
private String next;
private Lamp(boolean lighting, String opposite, String next) {
this.lighting = lighting;
this.opposite = opposite;
this.next = next;
}
publicboolean isLight(){
returnlighting;
}
//当灯变绿的的时候,对应的灯也变绿
publicvoid light(){
this.lighting=true; //设置为绿灯
if(opposite!=null){
Lamp.valueOf(Lamp.this.name()).isLight(); //把对应的灯的字符串转变成枚举类型,并得到灯的状态
}
System.out.println(name() + " lamp is green,下面总共应该有6个方向能看到汽车穿过!");
}
//当灯变红的时候,对应的灯也变红,并且下一盏灯变绿
public Lamp blackOut(){
this.lighting=false;
if(opposite!=null){
Lamp.valueOf(next).isLight();
}
Lamp nextLamp=null; //定义下一盏灯
if(next!=null){ //如果有下一盏灯
nextLamp=Lamp.valueOf(next);
nextLamp.light();
}
return nextLamp;
}
}
灯控制器:
灯控制器中有一个属性: Lamp currentLamp---(当前的灯)
在灯控制器中先指定一盏灯为绿灯 , 然后通过计时器来给绿灯计时, 当时间到的时候,把当前绿灯变红, 然后返回下一个绿灯.
import java.util.concurrent.*;
publicclass LampController {
private Lamp currentLamp; //当前灯
LampController(){
currentLamp=Lamp.S2N; //指定一个当前灯
currentLamp.oppoLamp(); //把当前灯变绿灯
ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable(){
@Override
publicvoid run() {
// TODO Auto-generated method stub
currentLamp=currentLamp.blackOut();
}
},
10, 10,
TimeUnit.SECONDS);
}
}
路线:
车辆是在路线上,所以要在路线的构造函数上初始化一些车辆,而这些车辆不可能一瞬间就出现了,所以应该要有间隔时间.
路线还有一个方法来移除车辆,当绿灯的时候,会每个一定时间移除车辆集合中的第一个辆车
/*
* 车辆是在路线上,所以要在路线的构造函数上初始化一些车辆,而这些车辆不可能一瞬间就出现了,所以应该要有间隔时间.
* 路线还有一个方法来移除车辆,当绿灯的时候,会每个一定时间移除车辆集合中的第一个辆车
* */
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
publicclass Road {
private List<String> vehicles =new ArrayList<String> (); //创建一个集合,存放车辆
private String name=null; //路线的名字
Road(){
this.name=name;
//创建一个线程池
ExecutorService pool=Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){
@Override
publicvoid run() {
// TODO Auto-generated method stub
//产生50辆车
for (int i = 0; i < 50; i++) {
try {
//随机睡眠
Thread.sleep((new Random().nextInt(10)+1)*1000);
vehicles.add(Road.this.name+"_"+i);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
});
//一个计时器,每一秒钟就移除一辆车
ScheduledExecutorService timer=Executors.newScheduledThreadPool(1); //创建一个计时器,接收一个线程池
timer.scheduleAtFixedRate(new Runnable(){
@Override
publicvoid run() {
// TODO Auto-generated method stub
if(vehicles.size()>0){ //如果有车
boolean lighted=Lamp.valueOf(Road.this.name).isLight(); //得到路线上灯的状态
if(lighted){
System.out.println(vehicles.remove(0)+"开走啦!");
}
}
}
},
1, //一秒中后做一件事
1, //隔1秒再做下一次
TimeUnit.SECONDS); //时间的单位
}
}
主函数:
在主函数中,要创建12条路线的对象,可以使用循环.并且要创建一个灯控制器.
publicclass MainClass {
publicstaticvoid main(String[] args) {
String[]lamp={"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S" };//初始化路线
//创建路线
for (int i = 0; i < lamp.length; i++) {
new Road(lamp[i]);
}
new LampController();
}
}
总结:
在学习交通灯控制系统的过程中大量用到jdk1.5的新特性: 枚举. 使用枚举极大的简化了开发难度. 并且还复习了内部类要访问外部类的成员,需要用外部类名.this.成员名的方法, 除此之外,还学到了使用计时器: ScheduledExecutorService.
在学习的过程中,通过老师的讲解和一步一步的实践, 对面向对象的设计思想有了更深刻的认识, 受益匪浅.
---------------------- android培训,java培训、期待与您交流! ----------------------
详细请查看http://edu.csdn.net/heima