——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——

1,交通灯管理系统原理与分析

     首先明白它的工作原理,由于刚刚学车,大概明白交通灯是如何运作的,一般来说车右转是默认不用看灯的,可以直接右转的,

     但有时候当交通有箭头显示的时候又不一样了,所以我们不考虑这种情况。那么默认右转灯是一直绿的。根据东南西北四个方向

     的车都有各自的三种路线,按道理,东南西北四个方向都有各自的三个方向的交通灯。从车方面考虑就有123x4)种路线,而

  对应的交通灯也有12个。现在单从一个方向去讨论,比如说南(South)的方向,有三种情况,向右转(即南到东方向)是不用理的,

  所以剩下直行(南到北)和左转(南到西),假设直行的灯变绿了,则对应方向(北到南)也要变绿。直行的灯变红后,则对应方向

 (北到南)也要变红,而下一个灯左转(南到西)就要变绿。其他方向也是这么分析。

2,车和灯和灯控制的分析

     车:12种路线的车每个一段时间就在该路线添加一辆车,每秒检查当前方向的灯是否变绿,如何变绿则当前方向的车就要删除。

     灯:12种方向的灯,南(South)的方向,有三种情况,向右转(即南到东方向)是不用理的,所以剩下直行(南到北)和左转(南到西),

     假设直行的灯变绿了,则对应方向(北到南)也要变绿。直行的灯变红后,则对应方向(北到南)也要变红,而下一个灯左转(南到西)就要变绿。所以基本上每种方向的灯要关联两个相关方向的灯。

     路:一共有12种路线,每个路线要要与相同方向的车对应。

3,面向对象思想设计交通灯系统

 (1)  :很明显这是自定义的一种类,而最好的实现方式就是java的枚举类来实现。

      每个Lamp元素代表一个方向上的灯,总共有12个方向,所有总共有12Lamp元素。

      有如下一些方向上的灯,每两个形成一组,一组灯同时变绿或变红,所以,程序代码只需要控制每组灯中的一个灯即可:s2n,n2s  s2w,n2e  e2w,w2e

             e2s,w2n   s2e,n2w  e2n,w2s。上面最后两行的灯是虚拟的,由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制,

      所以,可以假想它们总是绿灯。所以一共有12lamp元素,实际上用到的是4组灯即四个方向的灯。lamp元素的构造方法里应该有上面分析过

      的两个相关联方向的灯,还有一个自己灯状态的值(false或者true)。灯应该有判断自己灯状态的方法,还有变绿和变红的方法。

        灯的代码如下:

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 Lamp(String opposite,String next,boolean lighted){

this.opposite = opposite;

this.next = next;

this.lighted = lighted;

}

  /*当前灯是否为绿*/

private boolean lighted;

/*与当前灯同时为绿的对应方向*/

private String opposite;

/*当前灯变红时下一个变绿的灯*/

private String next;

public boolean isLighted(){

return lighted;

}

 /**

 * 某个灯变绿时,它对应方向的灯也要变绿

 */

public void light(){

this.lighted = true;

if(opposite != null){

Lamp.valueOf(opposite).light();

}

System.out.println(name() + " lamp is green,下面总共应该有6个方向能看到汽车穿过!");

  }

  /**

 * 某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿

 * @return 下一个要变绿的灯

 */

public Lamp blackOut(){

this.lighted = false;

if(opposite != null){

Lamp.valueOf(opposite).blackOut();

}

  Lamp nextLamp= null;

if(next != null){

nextLamp = Lamp.valueOf(next);

System.out.println("绿灯从" + name() + "-------->切换为" + next);

nextLamp.light();

}

return nextLamp;

}

} 

   (2)   路线:一共有12条路线,即要产生12个实例对象,每条路线上随机增加新的车辆,而车就可以添加到一个集合中保存。

         以便处理。每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存车的集合中的第一辆车删除,即表示车穿过了路口。

                   路的类,路有自己路线的名字,而路线上的车的名字应该相同,都用字符串表示,如“s2n”,车辆不断随机上路的过程最好用线程来实现,

         而添加车辆的过程可以用for循环来实现。既然有添加车辆就要删除车辆,因为是通过每秒中检查当前路线的灯是否为绿的,所以也要用线程来实现,

         判断当前路线的灯是否为绿,如果为绿,则删除最前面的车辆,即第一部车。

          路的代码如下:

public class Road {

private List<String> vechicles = new ArrayList<String>();

   private String name =null;

public Road(String name){

this.name = name;

  //模拟车辆不断随机上路的过程

ExecutorService pool = Executors.newSingleThreadExecutor();

pool.execute(new Runnable(){

public void run(){

for(int i=1;i<1000;i++){

try {

Thread.sleep((new Random().nextInt(10) + 1) * 1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

vechicles.add(Road.this.name + "_" + i);

}

}

 });

 //每隔一秒检查对应的灯是否为绿,是则放行一辆车

ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);

timer.scheduleAtFixedRate(

new Runnable(){

public void run(){

if(vechicles.size()>0){

boolean lighted = Lamp.valueOf(Road.this.name).isLighted();

if(lighted){

System.out.println(vechicles.remove(0) + " is traversing !");

}
}
}
},
1,
1,
TimeUnit.SECONDS);
 }
}

  (3)  灯的控制类:每隔10秒将当前绿灯变为红灯,并让下一个方向的灯变绿。所以也要通过线程来实现。

        代码如下:

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.blackOut();

}

},
10,
10,
TimeUnit.SECONDS);

}
}

  (4)  启动程序

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();

}
}

  总结:

         难点:

               1.交通系统的业务逻辑不容易了解。

               2.处理的各种交通情况比较多,需要用到枚举类细化每个情况

               3.如何以面向对象的思想思考:如何设计类,以及类的属性和行为。类与类之间有什么关系和相互影响。