黑马程序员_Java交通灯案例

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

 

Blog12_1交通灯管理系统需求分析

需求:用代码实现生活中红绿灯的运作,并模拟车辆通过(只需要在控制台中模拟)。


(1)首先分析各个方向到来的车辆可能走的总路线条数

根据上图分析所有可能的路线为:

① S2N,S2E,S2W

② W2E,W2N,W2N

③ E2W,E2N,E2S

④ N2S,N2W,N2E

其中2的意思为”to”(程序员常用的一种方式)。

(2)简化编程模型

分析图可知南北,东西方向上的红绿灯的运作具有对应性,故为了简化编程模型,先考虑南方和东方来的车的编程实现。这样路线就可以简化到6条分别是:

S2N,S2E,S2W、E2W,E2N,E2S

又由于任何方向上右转的车辆都能畅通无阻,故又舍去两条线。故我们最后要考虑的就只有4条线,分别是S2N,S2W、E2W,E2S。通过这样简化问题,我们就可以思路清晰的编程了,另外为了统一编程的模型,我们设想每一条线上都有相对应的一个红绿灯。

(3)各个方向上灯的逻辑关系

假设南北方向上的车辆先通行,则各个方向上车辆的状态为:

① 南北方向上的车辆先通行,东西方向停止通行,所有左拐方向停止通行,右转通行。

② 南北方向上的车辆停止了,东西方向上停止通行,南北方向上所有左拐的通行,右转通行。

③ 东西方向上车辆通行,南北方向上车辆停止通行,所有方向上左拐停止通行,右转通行。

④ 东西方向山车辆停止,南北方向车辆停止通行,东西方向左拐车辆通行,右转通行。

Blog12_2交通灯管理系统面向对象的设计

上面过程中所涉及到的类有

车辆:根据”谁拥有数据谁就提供操作数据的方法原则”车辆类应该具有增加和减少车辆的方法。

路:由于编程模型的统一(每条路线都拥有各自路线上的路灯),我们可以把路和路灯融合在一个对象里面。

为了使车辆和路灯的逻辑清晰,我们同时设计一个控制各个类逻辑的类。

逻辑类:控制车辆和路灯的逻辑。

Blog12_3编写Road类中模拟汽车上路的代码

public class Road {
   private String name;
   private List<String> vehicle = newArrayList<String>();
   public Road() {
   }
   public Road(String name) {
      this.name = name;
      ExecutorService pool = Executors.newSingleThreadExecutor();
      pool.execute(new Runnable() {
         @Override
         public void run() {
            int i = 1;
            Random rd = new Random();
            while (true) {
               try {
                   Thread.sleep((rd.nextInt(10)+ 1) * 1000);
                }catch(InterruptedException e) {
                   e.printStackTrace();
                }
      vehicle.add(Road.this.name + "方向上第:" + i + "辆车通过");
                // System.out.println(Road.this.name + "方向上
//第:" + i + "辆车通过");
                i++;
            }
         }
      });
      ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
      timer.scheduleAtFixedRate(new Runnable() {
         @Override
         public void run() {
            if (vehicle.size() > 0) {
                boolean lighted = true;// 后面编程控制灯
                if (lighted) {
                   System.out.println(vehicle.remove(0)+"");
                }
            }
         }
      },1, 2, TimeUnit.SECONDS);
   }
}

上面代码中使用了线程并发库中的ExecutorService类,它能提供一个线程池(注意:是提供了一组线程来执行任务),当任务放到线程池中是,系统自动调用空闲的线程来执行任务,上面还使用了ScheduledExecutorService类的一个定时器功能,定时器的含义是:开始运行后经过初始化的时间后,按照设定的间隔时间,不断执行设定的任务,设定的任务不需要用while循环。而一般线程执行的任务都带有while循环。

Blog12_4编写一个红绿灯的类(lamp)

思路:由于所有的右转的车任何时候都畅通无阻,所以我们使所有右拐路线上的交通灯常绿(true),又由于相对方向上的交通灯状态完全一致,故我们实际编程中,剔除相同的,即主要只要考虑四条线上的交通灯情况,如只要考虑:

S2N,S2W, E2W, E2S,其他方向上的状态可以根据这四个状态对应推导出来。这能大大简化了我们编程的复杂程度,另外由于全部路线上的灯加起来是固定的12个,而且考虑到如果用一般类的话,后面创建对象的代码将很多,故我们想到了用枚举的方法来实例化十二方向上的交通灯。

   实现步骤:

A.  列出十二条线上的交通灯的枚举值

B.  定义lightednextoppsite属性。本例中定义的next和oppsite属性,能把同一规律的交通灯同一来处理,这也简化了代码的冗长。

C.  定义能获取任意路线上交通灯状态的方法isLighted();定义让指定灯变绿同时让对应的灯也变绿,下一灯变红的方法light();定义让指定灯变红同时让对应的灯也变红,下一灯变绿的方法light()

具体实现代码如下:

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);
   // 定义一个Lamp oppsite把相对应的一类灯统一
   private String oppsite;
   // 定义一个Lamp next把下一个灯统一
   private String next;
   // 灯状态属性
   private boolean lighted;
   private Lamp(String oppsite,String next, boolean lighted) {
      // 构造方法中不能使用枚举的值?
      this.oppsite = oppsite;//
      this.next = next;
      this.lighted = lighted;
   }
   // 判断灯状态的成员方法
   public boolean isLighted() {
      return lighted;
   }
   // 让对应路上灯亮的方法,同时还让对应的灯亮,下一个灯熄灭
   public void light() {
      this.lighted = true;
      if (oppsite != null) {
         Lamp.valueOf(oppsite).light();
      }
   }
   // 让对应路上的灯熄灭的方法,同时还让下一个灯点亮。
   public Lamp blackOut() {
      this.lighted = false;
      if (oppsite != null) {
         Lamp.valueOf(oppsite).blackOut();
      }
      Lamp tempNext=null;
      if (next != null) {
         tempNext=Lamp.valueOf(next);
         tempNext.light();
         lookLight(next);
      }
      return tempNext;
   }
   // 打印出当前红绿灯状态的方法
   public void lookLight(String next2){
      // System.out.println("haahahaha");
      if (next2.equals("S2N")) {
         System.out.println("南北:绿----东西:红---禁止左行");
      }elseif(next2.equals("S2W")){
         System.out.println("南北:红----东西:红---南到西左行:绿");
      }elseif(next2.equals("E2W")){
         System.out.println("南北:红----东西:绿---禁止左行");
      }else{
         System.out.println("南北:红----东西:红---南到西左行:绿");
      }
   }
}

Blog12_5编写一个控制红绿灯逻辑关系的类

public class LampControl {
   private Lamp currentLamp;
   public LampControl() {
      currentLamp = Lamp.S2N;
      currentLamp.light();
      ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
      timer.scheduleAtFixedRate(new Runnable() {
         @Override
         public void run() {
            currentLamp = currentLamp.blackOut();
         }
      },5, 5, TimeUnit.SECONDS);
   }
}

定义一个currentLamp当前灯,初始化当前灯为S2N并设置其为绿灯,仍然采用Executors的定时器功能,然后在定时器的内部加上切换路线上灯的代码currentLamp =currentLamp.blackOut();由于每执行完一次都能使此次的灯变红,并使下一个灯变绿,同时把下一个灯返回给currentLamp这样就能使灯不断的切换。

Blog12_6测试类的编写

      String[]dirction={
      "S2N","S2E","N2S","N2W",
      "N2S", "N2E","W2E","W2N",
      "S2E", "E2N","N2W","W2S"
      };
      for(int i=0;i<12;i++){
         new Road(dirction[i]);
      }
      LampControllc=new LampControl();
}

用数组和循环来初始化12条路线,然后在实例化路灯控制器。由于功能都写在构造函数内部,所以在实例化的同时程序就开始运行了。

 

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

详情请查看:http://edu.csdn.net/heima

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值