交通灯管理系统


 

需求:
    模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
    1.异步随机生成按照各个路线行驶的车辆。
    例如:
           由南向而来去往北向的车辆 ---- 直行车辆
           由西向而来去往南向的车辆 ---- 右转车辆
           由东向而来去往南向的车辆 ---- 左转车辆
           。。。
    2.信号灯忽略黄灯,只考虑红灯和绿灯。
    3.应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
    4.具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
    注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
    5.每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
    6.随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
    7.不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
面向对象的分析与设计:
    1.车的通行方式:先由南北通向直行,直行以后是南北通向的左转弯的车辆通行。
    接下来是东西方向的直行车辆,直行后是东西通向的左转弯车辆。
    之后再次是南北直行车辆,如此循环交替行驶。
    2.设想一下有哪些对象:红绿灯,红绿灯的控制系统,汽车,路。汽车看到自己所在的路线对应的灯
    绿了就穿过路口吗?不是,还需要看其前面是否有车,该问那个对象呢?该问路,路中存数这车辆的
    集合,显然路上就应该有增加车辆和减少车辆的方法了。回顾题目,我们这里并不要体现车辆移动的
    过程,只是捕捉出车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,所以,这个车并不需要
    单独设计成一个对象,用一个字符串表示就可以了。

    面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。在牢牢掌握几
    个典型的案例就可以了:人在黑板上花园,列车司机紧急刹车,售货员统计收货小票的金额。
    两块石头磨成一把石刀,用石刀把树砍成木材,用木材做成椅子。实现模拟:
    StoneKnife = KnifeFactory.createKnife(stone);石头工厂把石头变成石刀。
    Mood = StoneKnife.cut(tree);石刀把树砍成木材
    Chair = ChairFactory.makeChair(mood);椅子工厂把木材做成椅子。
    为什么不把做椅子的方法分配给木材呢?
    因为,木材把自己变成椅子后,木材对象就不存在了。把自己变没了。不科学。
代码如下:
Road类:
public class Road {      //每条路线
    private String name = null;     //路的名字
    List<String> verchicles = new ArrayList<String>();   //
    public Road(String name){
       this.name = name;
       //为了避免构造方法出现难产状况。调用此构造方法时,创建线程池,并创建一个产生车的线程。
       Executors.newSingleThreadExecutor().execute(new Runnable(){
           public void run() {
               //开线程产生1000两车,并给名字(路名+车辆的序号)
               for(int i=1;i<=1000;i++){
              try {//休息,110秒内随机出现一辆车
                  Thread.sleep((new Random().nextInt(10)+1)*1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
                  verchicles.add(Road.this.name+"_"+i);
              }
           }     
       });
       //定时器
       Executors.newScheduledThreadPool(1).scheduleAtFixedRate( 
              new Runnable(){
                  public void run(){
                     if(verchicles.size()>0){//判断是否有排队的车辆
                         //获取当前车辆所在路线的灯是否为绿色。
                         boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
                         if(lighted){//判断,如果为绿灯。从集合中移走已经路过路口的车,并打印
                            String verchicle = verchicles.remove(0);
                            System.out.println(verchicle+"  is travering");
                         }
                     }
                  }
              },
              1,
              1,
              TimeUnit.SECONDS);  
    }
}

Lamp类:
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 String opposite;
    private boolean lighted;
    private String next;
    private Lamp(){
    };
    //枚举的构造方法必须为私有,opposite:与之对应的灯,next:下一个要亮的灯,lighted:灯的初始状态
    private Lamp(String opposite,String next,boolean lighted){
       this.opposite= opposite;
       this.next = next;
       this.lighted = lighted;
    }
    public boolean isLighted(){
       return this.lighted;
    }
    public void light(){
       System.out.println(name()+" is green.下面可以看到六个方向的车辆运行");
       this.lighted= true;
       if(this.opposite!=null){
           //lamp.valueOf(str)将字符创转换为相应的枚举类型。
           Lamp.valueOf(opposite).light();
       }
    }
    //此灯变黑的同时,要将下一个灯点亮。并且返回下一个灯的对象nextLamp,为了方便下一次调用此方法。
    public Lamp blackOut(){
       this.lighted = false;
       if(this.opposite!=null){
           Lamp.valueOf(opposite).blackOut();
           System.out.println("aaa");
       }
       Lamp nextLamp =null;
       if(this.next!=null){
           nextLamp = Lamp.valueOf(this.next);
           System.out.println("绿灯从"+name()+"切换为------->"+next);
           nextLamp.light();
       }
       return nextLamp;
    }
}

LampController类:
//实现灯的按时亮灭控制
public class LampController {
    private Lamp currentLamp;
    public LampController(){
       currentLamp = Lamp.S2N;
       currentLamp.light();
       Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
              new Runnable(){
                  public void run(){
                     currentLamp = currentLamp.blackOut();
                  }
              },
              10,
              10,
              TimeUnit.SECONDS);
    }
}

MainClass类:
public class MainClass {
    public static void main(String[] args) {
        String[] directions = new String[]{"N2S","N2E","W2E","W2N",
                "S2N","S2W","E2W","E2S","N2W","W2S","S2E","E2N"};
        //创建12个路对象
        for(int i =0;i<directions.length; i++){
            //因为路内部有定时器和创建车辆的线程,所以路对象不会马上被GC回收,
            //只有等1000辆车都通过后对象才会失效。
            new Road(directions[i]);
        }
        //创建一个灯控制器。
        new LampController();
    }
}

定时器:
    scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
    按照固定的频率重复一件事
    参数:command:要执行的事务,实现Runnable接口,和run方法。run方法中存放要执行的事务;
    参数:initialDelay:第一次延迟多少时间以后执行command事务;
    参数:period:以后每次循环的周期;
    参数:unit:定义时间单位;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值