黑马程序员_java学习日记_面试题_交通灯管理系统
遇到问题不要偷懒,画图有助于理解问题
车辆的行驶顺序,先是直线,比如南向北,然后是左拐外南向西,其他三个方向类似
除去不受控制的灯,这样只剩下8条需要考虑,而这8条中都是成对出现的,所以只需要考虑四条就可以
右拐弯也有灯。只不过是常绿的
绿灯情况下,先是直行,后是拐弯,然后换灯
面向对象:
首先考虑这个情景有哪些对象
灯,灯的控制系统,汽车,路线
路线和灯绑定。汽车看到自己路上所对应的的灯绿了才会走,还要看前面是否有车,也就是说只有自己是第一个位置才能行走,于是路应该有add和remove方法用于增删车辆
路上的车可以看做是一个集合,于是路就应该有增加车辆和减少车辆的方法
面向对象设计的重要经验:谁拥有数据,谁就对外提供操作这些数据的方法,谁就是类
面向对象的分析涉及:人在黑板上画圆?? 人黑板园
关于灯的设计
无论何时都是12个灯,因此用到枚举
当一个灯变绿,相反方向的灯也会变绿,当一个灯变红,相反方向的灯也变红,而下一个等要变红或变绿,所以该枚举至少俩参数,对面的灯和下一个灯,还有一个参数是自己的状态,自己是不是绿的
灯变红和变绿方法应该返回下一个灯
首先创建一个类road,不同的路线有不同的名字,因此提供含参构造方法,构造方法里面不能sleep,否则永远不返回
publicclass Road {
???
??? //定义一个集合用来存储车辆
??? private List<String> list = new ArrayList<String>();
??? //路线的名字
??? private String name = null;
??? public Road(String name)
??? {
?????? this.name = name;
?????? //假设每1S路上上来一辆车,其他的不管
?????? //车应该一辆辆上来,而不是一下子全部上来,因此要用计数器
?????? //创建一个使用单个 worker 线程的 Executor 线程池
?????? ExecutorService pool = Executors.newSingleThreadExecutor();
?????? //如果有一个任务,交给一个线程池,线程池自己挑一个空闲的线程去执行他
?????? pool.execute(new Runnable()//{}表示new了一个runnable的实现类对象
?????? {
?
?????????? @Override
?????????? publicvoid run() {
????????????? for(int i = 0 ; i < 100 ; i++)
????????????? {
????????????????? try {
???????????????????? //随机1-10秒钟上来一辆车
???????????????????? Thread.sleep((new Random().nextInt(10)+1)*1000);
???????????????????? //访问外部类成员变量本来可以直接访问,但如果外部类的变量名字和内部类的相同则需要外部类.this.属性名
????????????????? } catch (InterruptedException e) {
???????????????????? e.printStackTrace();
????????????????? }
????????????? ??? list.add(Road.this.name+":"+i);
????????????? }
?????????? }
?????? });
?????? //创建一个调度池
?????? ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
?????? //计时器每个多长时间去干这件事。参数为要执行的代码,多少秒之后去做,每隔多少秒去做,计时单位
?????? //重载形式是多少秒之后去做,只做一次
?????? //timer.schedule(command, delay, unit)
?????? timer.scheduleAtFixedRate(new Runnable(){
?????????????????
??????????????????????????? @Override
??????????????????????????? publicvoid run() {
??????????????????????????????? //检查有没有车
??????????????????????????????? if(list.size() > 0)
??????????????????????????????? {
?????????????????????????????????? //假如灯是绿的
?????????????????????????????????? if(Lamp.valueOf(Road.this.name).isGreen())
?????????????????????????????????? {
?????????????????????????????????????? //remove方法返回值是被移除的元素
?????????????????????????????????????? System.out.println(list.remove(0)+"is removed!");
?????????????????????????????????? }
??????????????????????????????? }
???????????????????????????????
??????????????????????????? }},
??????????????????????????? 1,
??????????????????????????? 1,
??????????????????????????? TimeUnit.SECONDS);
??? }
}
创建灯.java
?
?
publicenum Lamp {
?
??? //S2N,S2W,E2W,E2S,N2S,N2E,W2E,W2N,S2E,E2N,N2W,W2S
??? //不使用N2S而是“N2S”是因为必须先定义后使用
??? //第一个是对面的灯,第二个是下一个灯,第三个是灯是否是亮的
??? 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);
??? //点亮灯
??? privatebooleangreen;
??? //对应的灯的名字,为了解决先定义后使用的问题直接使用对象无法继续写
??? private String opposite;
??? //下一个灯
??? private String next;
??? //枚举的构造方法必须私有
??? private Lamp(String opposite,String next,boolean green)
??? {
?????? this.opposite = opposite;
?????? this.next = next;
?????? this.green = green;
??? }
??? private Lamp()
??? {
??????
??? }
???
??? //是否是亮的
??? publicboolean isGreen()
??? {
?????? returngreen;
??? }
??? publicvoid becomegreen()
??? {
?????? //opposite.becomegreen(); 我的灯亮了,就让对应的灯也亮,但是不能这样写,会陷入死循环
?????? this.green = true;
?????? //假如我为主,我有对应的灯,而对面的灯没有对应的灯
?????? if(opposite != null)
?????? {
?????????? Lamp.valueOf(opposite).becomegreen();
?????? }
?????? System.out.println(name()+"变绿了");
??? }
??? public Lamp becomered()
??? {
?????? this.green = false;
?????? if(opposite != null)
?????? {
?????????? Lamp.valueOf(opposite).becomered();
?????? }
?????? Lamp nextLamp = null;
?????? if(next != null)
?????? {
?????????? nextLamp = Lamp.valueOf(next);
?????????? nextLamp.becomegreen();
?????? }
?????? System.out.println(name()+"变红了");
?????? return nextLamp;
??? }
}
灯的控制器
publicclass LampControler {
??? private Lamp currentLamp;
???
??? public LampControler(){
?????? //加定第一个灯为E2N,然后让他变绿灯
?????? currentLamp = Lamp.S2N;
?????? currentLamp.becomegreen();
?????? ScheduledExecutorService c = Executors.newScheduledThreadPool(1);
?????? c.scheduleAtFixedRate(new Runnable(){
?????????? @Override
?????????? publicvoid run() {
????????????? System.out.println("来啊");
????????????? //因为该方法需要下一个灯作为返回值使灯来回切换所以becomered方法需要返回下一个灯
????????????? currentLamp = currentLamp.becomered();
?????????????
?????????? }
??????????
?????? },
?????? 10,
?????? 10,
?????? TimeUnit.SECONDS);
??? }
}主类
?
publicclass Main {
?
??? /**
??? ?* @param args
??? ?*/
??? publicstaticvoid main(String[] args) {
?????? String[] str = new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
?????? for(String s : str)
?????? {
?????????? new Road(s);
?????? }
?????? new LampControler();
??? }
?
}