黑马程序员——交通灯管理系统

本文分享了作者在学习交通灯系统时的心得体会,包括如何运用面向对象编程思想,解决实际问题。通过画图理解逻辑,明确对象角色,并运用线程池、枚举等新知识解决具体问题。文章附带了详细代码注释,帮助读者更好地理解和学习。
---------------------- android培训 java培训 、期待与您交流! ----------------------

          昨天学习了交通灯系统,今天又从新看了一下。下个小总结吧。刚一看就懵了,发现原来用的知识怎么都没用上?这一个月来的努力白费了吗。里边不仅加了计时器,线程池,等等新的知识,都是以前没见过的,之后又中很大的失落感,只有又硬着头皮重新看,第二次看的当中,发现了很多小知识点,象匿名内部类了,内部变量访问外部局部变量的方法,等等,得到了温故而知新的效果,而且用上了张老师的关于枚举的一些新知识,交通灯的12条路线用枚举真的很简单。就像张老师说的那样,看到新知识不能害怕,不要觉得没学过,只要用过一次就学会了,以后碰到类似的问题就可以举一反三了。
        学到的最重要的就是如何使用面向对象,里边很重要的一句就是谁拥有数据,谁就对外提供了针对这个数据进行操作的方法。或者这句话现在还不是很了解。但是随着我学习的深入,会慢慢的去了解的。
       像这个例子中,第一步就是画图,弄懂路和灯之间的逻辑。画图也非常有助于理解和分析问题,然后分析这个题目中有几个对象?首先,车是怎么运行的?他是要受到路和灯的控制,车该往哪里走?谁最清楚?灯和路最清楚,灯给车提供了信号,我让你走你才能走,你的听我的,我说的算。路会告诉车下一步 你直走还是转弯等等。所以在这里灯和路都是对象,在考虑灯,他会自己变红变绿吗?不会,谁在控制?lampControllor 他告诉我什么时候亮什么时候红。所以整个项目中的3个对象就明确了。这就是面向对象的思想吧。
      可能我的基础还比较薄弱,对这个项目理解的也不好,现在的了解也只是皮毛。其中的精髓还没有领悟到,等以后基础好点,我会再回来看这道非常经典的项目,不然也对不起张老师。。。
       下边是我根据张老师的视频,跟着打的代码。注释很多,欢迎拍砖。

class Road{
List<String> vechicles = new ArrayList<String>();

private String name = null;
public Road(String name){
  this.name=name;
  //第一个name是成员变量,第二个name是传进来的name是成员函数的局部变量
  //这里要用一个线程池。1.5以上,线程池是一上来就产生好多个线程,有任务交给他运行的时候,看哪个空闲就交给他们去运行。
  //当前我只需要一个线程 那么在线程池上标1. 线程池是一组线程,可以建立一个线程池,让他交给某个线程去做,
  //我不交给某个线程,我要交给这个线程池。让他去调用某个线程。
  //ExecutorService也是个线程池,等同于pool
  ExecutorService pool = Executors.newSingleThreadExecutor();//执行器,如果一个类用作工具 它里边的方法全是静态方法,这个类的名字往往以类打头。像utils
  pool.execute(new Runnable(){//这相当于new了一个Runnable实现类的对象,接口是不能直接new的,但是加个大括号表示new的是他的实现类
   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);//加上车的名字和第几辆车。
     //内部类要访问外部类的局部变量,局部变量要加final
     //访问外部类的成员变量本来可以直接用外部类成员变量的名字,但是如果这个变量与自己类中的变量名字打架了就必须不能省略Road.this.
    }   
   }
  });

  //定义一个定时器
  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==true){
        System.out.println(vechicles.remove(0)+"is traversing!");
        //这里返回的是 被移走的那个东西。
       }
      } 
     }
    },
    1,//过多少秒之后去干这个事
    1, //干完之后在过多少秒接着干?
    TimeUnit.SECONDS);//这个是前面数字的计数单位
  /*timer.schedule(
    new Runnable(){},
    delay,//delay就是过多长时间干conmand这件事
    unit);*/
}
}
enum Lamp {
S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),//只要控制住这四条线路就ok
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.opposite = 传过来的opposite
  this.next = next;
}
private Lamp(){//这里要补一个无参构造方法,因为上边的元素有的没有参数,
    //为了让他们不报错,才搞一个这个
}
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(); //这里是获得字符串opposite的对象.变绿  
  }//我有对应的灯的时候我才让对应的灯亮 比如我东亮了,东对应的西就亮了,
  //这时西就没对应的灯了,不然就死循环了
  System.out.println(name()+"Lamp is Green,下边应该有六个方向能看到汽车通过");
}

public Lamp blackOut(){//灯变红
  this.lighted = false;
  if(opposite != null){
   Lamp.valueOf(opposite).blackOut();  
  }
  Lamp nextLamp = Lamp.valueOf(next);
  if(next != null){
   System.out.println("绿灯从"+"-------》切换为"+next);
   nextLamp.light();
  }
  return nextLamp;
}
}


class LampController {
private Lamp currentLamp;
public LampController(){
  currentLamp = Lamp.S2N;
  currentLamp.light();
 
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
  timer.scheduleAtFixedRate(
    new Runnable(){
     public void run(){
      currentLamp = currentLamp.blackOut();//当前的灯变黑,我的当前灯应该指向新变绿的灯。
     }
    },
    2,
    2,
    TimeUnit.SECONDS);
}
}
class MainClass {

/**
  * @param args
  */
public static void main(String[] args) {
  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();
}
}

---------------------- android培训 java培训 、期待与您交流! ----------------------
Ymodem协议是一种在串行通信中用于数据传输的机制,起源于早期的Xmodem协议。该协议具备处理大容量数据文件的能力,支持数据校验、文件属性传递以及多文件批量传输。Qt是一个面向C++的跨平台开发框架,适用于构建图形界面程序及后台服务类应用。当结合Qt实现Ymodem协议时,能够开发出适用于多种设备的通信程序,包括桌面系统、嵌入式设备和移动终端。 在Qt中实现Ymodem协议,需要掌握Qt的信号与槽机制、串口通信模块(如QSerialPort)以及线程管理技术。实现过程中通常包含以下主要环节: 1. 连接初始化:在通信双方确认状态后,启动数据传输流程。 2. 数据块传输:协议支持多种数据块大小,如128字节或1024字节。每个数据块需包含数据内容、编号及校验信息。接收端需对数据进行校验以保证完整性。 3. 序列管理与响应机制:通过编号确保数据顺序,发送端在收到确认信号后继续下一块传输。若未收到有效响应,则需重传。 4. 文件元信息传输:在正式传输前,发送方需传递文件名称及大小等信息,以便接收方进行存储准备。 5. 批量传输模式:支持多个文件的连续传输,需在数据中区分不同文件的块。 6. 传输结束机制:通常通过发送空数据块来终止通信过程。 在Qt中实现Ymodem协议的代码,通常需要创建多个类来封装串口通信逻辑及协议处理功能,同时需考虑异常处理和数据恢复策略。代码涉及对QSerialPort的配置、数据流的监控、事件循环的管理等。此外,为提升用户体验,开发人员可能在代码中加入进度显示、传输速率计算等功能。 Qt的跨平台特性使得基于其开发的Ymodem协议实现具备良好的可移植性,可在不同操作系统上运行。开发此类程序需要开发者对Ymodem协议有深入了解,并熟悉Qt框架的使用,包括信号机制、多线程及串口通信等技术。高质量的代码实现能够确保协议在不同运行环境下的稳定性与可靠性。 Ymodem协议的实现常出现在开源项目中,为开发者提供了参考和借鉴,有助于技术交流与社区发展。根据文件名“SerialPortYmodem”推测,该文件可能用于处理与串口通信相关的Ymodem逻辑。开发者在使用时应仔细查阅文档,理解各模块功能,以便正确集成和应用。 综上,Qt实现Ymodem协议的开发涉及对协议机制与Qt框架的深入理解,能够构建出满足多种串行通信需求的程序。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值