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

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

2013-11-17 20:28 477 查看
-------------- android培训java培训、期待与您交流!
---------------
1.需求分析



图解还原十字路头的车流情况:



2.面向对象的分析:
 1.每条路线上都会出现多辆车,路线上要随机增加新的车,在灯绿期间还要每秒钟减少一辆车。

  2.每条路线每隔一秒都会检查控制本路线的灯是否为绿,一个灯由绿变红时,应该将下一个方向的灯变绿。

根据分析:
在整个项目中我们可以分析出来三个对象。
路线:
     路上有很多车,我们可以把车忽略不计成一个对象,因为我们研究的主题就是路线和灯的问题。
    由此可以看出来在路这个对象中,他的变量就是车,方法那就是增加一辆车,和减少一两车。
灯:
   灯那控制着车的前进和停止,每一条路线我们都有一个灯(其中我们可以把每个路线向右转弯的灯看成永远是亮着的)。
   故我们在设计方法的时候,肯定要有开绿灯,开红灯的方法

控制器:
    控制着红绿灯的在一定频率的切换

Road

     ①每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合。
     ②在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车(用一个“路线名_id”形式的字符串进行表示)。
     ③在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和将集合中的第一辆车移除掉。

package cn.itheima.traffic;

/**
* 路
*@author zhangyun
*/

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 {
private List<String> vehicles = new ArrayList<String>();
private String name;

public Road(String name) {
this.name = name;
// 模拟在路上随机增加100辆车,因为不可能等创建完100辆车之后才检查灯的状态,所以这里需要创建单独的线程执行
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(new Runnable() {
public void run() {
for (int i = 1; i < 100; i++) {
try {
Thread.sleep((new Random().nextInt(10) + 1) * 200);
} catch (InterruptedException e) {
e.printStackTrace();
}
vehicles.add(Road.this.name + '_' + i);
}
}
});

// 每隔1秒检查是否是绿灯,若是绿灯,则汽车通过,即减少一辆汽车
ScheduledExecutorService schedulePool = Executors
.newScheduledThreadPool(1);
schedulePool.scheduleAtFixedRate(new Runnable() {
public void run() {
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
if (lighted) {
System.out.println(vehicles.remove(0) + " is through");
}
}
}, 1, 1, TimeUnit.SECONDS);
}
}


Lamp类

    ①系统中有12个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将Lamp类用java5中的枚举形式定义更为简单。
    ②每个Lamp对象中的亮黑状态用lighted变量表示,选用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮,Lamp对象中还要有一个oppositeLampName变量来表示它们相反方向的灯,再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,相反方向和下一个方向的灯用字符串形式表示。
   ③增加让Lamp变亮和变黑的方法:light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。
   ④除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外,其他方向上的Lamp对象的nextLampName和oppositeLampName属性设置为null即可,并且S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null,以便防止light和blackOut进入死循环。

package cn.itheima.traffic;

/**
* 灯
* 共12种路线,即12种灯,向右转这种特殊方式把他看成绿灯,一直可通行
* 另外8种灯是相对的,可以看成是4组,当灯亮时,对应的灯也亮,关闭也是同理
* 灯关闭的时候,下一个路口的等就要变亮
* @author zhangyun
*/

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),W2
a840
E(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;
//相对应的灯
private String opposite;
//下一个灯
private String next;
private Lamp(String opposite, String next, boolean lighted){
this.opposite=opposite;
this.next=next;
this.lighted=lighted;
}

//检查灯的状态
public boolean isLighted(){
return lighted;
}

//亮灯操作,若存在相对的等,则相对的等也需要亮灯
public void light(){
this.lighted=true;
if(opposite!=null){
Lamp.valueOf(opposite).light();
}
System.out.println(name()+"变为绿灯,共有6个方向可以通行");
}
//关灯操作,关闭此等后需要吧下一个灯点亮,这里需要返回下一个灯,因为在LampController中,每10秒关闭灯,开启下一个灯,需要将nextLamp赋值给currentLamp
public Lamp closeLight(){
this.lighted=false;
if(opposite!=null){
Lamp.valueOf(opposite).closeLight();
}
Lamp nextLamp = null;
if(next!=null){
nextLamp=Lamp.valueOf(next);
System.out.println(name()+"灯变红,下一个灯:"+next+"变绿灯");
nextLamp.light();
}
return nextLamp;

}

}


LampController类

    ①整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
    ②LampController构造方法中要设定第一个为绿的灯。
    ③LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。

package cn.itheima.traffic;

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

/**
* 灯控制器:
* 控制红绿灯的切换
* @author zhangyun
*
*/
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(){
currentLamp = currentLamp.closeLight();
}
},
10,
10,
TimeUnit.SECONDS);

}

}


MainClass类

   ①用for循环创建出代表12条路线的对象。
   ②接着再获得LampController对象并调用其start方法。
package cn.itheima.traffic;

/**
* 测试类
* @author zhangyun
*
*/
public class MainClass {
public static void main(String[] args) {
String[] roads = new String[] { "S2N", "S2W", "E2W", "E2S", "N2S",
"N2E", "W2E", "W2N", "S2E", "E2N", "N2W", "W2S" };

//初始化12个方向的路
for (int i = 0; i < roads.length; i++) {
new Road(roads[i]);
}

// 打开控制器
new LampController();
}

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