——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——
1,交通灯管理系统原理与分析
首先明白它的工作原理,由于刚刚学车,大概明白交通灯是如何运作的,一般来说车右转是默认不用看灯的,可以直接右转的,
但有时候当交通有箭头显示的时候又不一样了,所以我们不考虑这种情况。那么默认右转灯是一直绿的。根据东南西北四个方向
的车都有各自的三种路线,按道理,东南西北四个方向都有各自的三个方向的交通灯。从车方面考虑就有12(3x4)种路线,而
对应的交通灯也有12个。现在单从一个方向去讨论,比如说南(South)的方向,有三种情况,向右转(即南到东方向)是不用理的,
所以剩下直行(南到北)和左转(南到西),假设直行的灯变绿了,则对应方向(北到南)也要变绿。直行的灯变红后,则对应方向
(北到南)也要变红,而下一个灯左转(南到西)就要变绿。其他方向也是这么分析。
2,车和灯和灯控制的分析
车:12种路线的车每个一段时间就在该路线添加一辆车,每秒检查当前方向的灯是否变绿,如何变绿则当前方向的车就要删除。
灯:12种方向的灯,南(South)的方向,有三种情况,向右转(即南到东方向)是不用理的,所以剩下直行(南到北)和左转(南到西),
假设直行的灯变绿了,则对应方向(北到南)也要变绿。直行的灯变红后,则对应方向(北到南)也要变红,而下一个灯左转(南到西)就要变绿。所以基本上每种方向的灯要关联两个相关方向的灯。
路:一共有12种路线,每个路线要要与相同方向的车对应。
3,面向对象思想设计交通灯系统
(1) 灯:很明显这是自定义的一种类,而最好的实现方式就是java的枚举类来实现。
每个Lamp元素代表一个方向上的灯,总共有12个方向,所有总共有12个Lamp元素。
有如下一些方向上的灯,每两个形成一组,一组灯同时变绿或变红,所以,程序代码只需要控制每组灯中的一个灯即可:s2n,n2s s2w,n2e e2w,w2e
e2s,w2n s2e,n2w e2n,w2s。上面最后两行的灯是虚拟的,由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制,
所以,可以假想它们总是绿灯。所以一共有12个lamp元素,实际上用到的是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.如何以面向对象的思想思考:如何设计类,以及类的属性和行为。类与类之间有什么关系和相互影响。