6.交通灯系统分析
l面向对象的知识点:
面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。
l系统分析:
1,十字路口的线路分析,共有12条线路。分别为:"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S";所以12条线路对应着12个灯,那么灯就可以看成一个对象,并且可以使用枚举类完成,灯的操作有变红,变绿和判断灯的状态。12个灯中有四个灯是右拐弯的所以只需常绿即可,剩下的8个灯都是两两对应的,所以主灯只需4个,其余4个让其与主灯的状态一一对应即可。另外在灯变红时还需要一将下一个灯变绿。
2,路和车两个对象,因考虑到车可以使用字符串来代替所以只需路一个对象。因路上的车需要增减的操作所以考虑可以使用集合来代表路。在路的对象中需要接收路线名,并且需要随机向路上添加车辆的操作和通过接收到的路线名来获取当前路线上的灯并每一秒判断当前路线上的灯的状态来让集合中的第一辆车通过。
3,因为灯需要进行管理,所以可以创建一个灯管理系统对象。类中需要对灯初始化一个开始灯(即设置一个灯为绿灯)并记录为当前灯,设置每格10秒对当前灯进行变红的操作(所以这里就需要在灯的类中对下一个灯变绿操作时返回这个变绿的灯)。
l具体代码实现:
//灯类
publicenum Lamp {
//四个主灯对象,构造时传递自身的状态,自己对面的灯和下一个灯
S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","S2N"),
//四个对面的灯,因主灯控制了所以这些对面的灯就不需要传递对面和下一个灯
N2S(false,null,null),N2E(false,null,null),W2E(false,null,null),W2N(false,null,null),
//四个右拐弯的灯需要一直绿,所以初始时传递状态为true
S2E(true,null,null),E2N(true,null,null),N2W(true,null,null),W2S(true,null,null);
//构造函数接收三个参数:灯的状态,对面灯名,下一个灯名
private Lamp(boolean lighted,String opposite,String next){
this.lighted = lighted;
this.opposite = opposite;
this.next = next;
}
privatebooleanlighted;
private Stringopposite;
private Stringnext;
//判断灯的状态
publicboolean isLighted(){
returnlighted;
}
//点亮绿灯并且把对面相同路线的灯变绿
publicvoid lightGreen(){
lighted =true;
if(opposite != null){
Lamp.valueOf(opposite).lightGreen();
}
}
//点亮红灯并且把对面相同路线的灯变红,同时把自己下一个灯变绿
public Lamp lightRed(){
lighted =false;
if(opposite != null){
Lamp.valueOf(opposite).lightRed();
}
Lamp nextLamp = null;
if(next != null){
nextLamp = Lamp.valueOf(next);
nextLamp.lightGreen();
}
return nextLamp;
}
}
//灯管理系统
publicclass LampController {
private LampcurrentLamp;
public LampController(){
currentLamp = Lamp.S2N;
currentLamp.lightGreen();
ScheduledExecutorServicetimer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
publicvoid run(){
currentLamp =currentLamp.lightRed();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
//路类
publicclass Road {
//定义一个集合作为路线
List<String>vecnicles =new ArrayList<String>();
private Stringname =null;
public Road(String name){
this.name = name;
//利用线程随机的向路上添加车辆
ExecutorService add= Executors.newCachedThreadPool();
add.execute(new Runnable(){
@Override
publicvoid run() {
for(int x=0; x<1000; x++){
try {
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
} catch (Exception e) {
e.printStackTrace();
}
//将路线名加编号作为车辆添加到路线上
vecnicles.add(Road.this.name + "_" + x);
}
}
});
//利用线程定时器将符合的车辆从路上移除
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
publicvoid run(){
if(vecnicles.size()>0){
//获取当面路线上的路的状态
boolean ligthed = Lamp.valueOf(Road.this.name).isLighted();
if(ligthed){
//如果当前路线上的灯为绿灯则第一辆车通过
System.out.println(vecnicles.remove(0)+"车正在通过...");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
总结:
通过这个题目了解到了面向对象的真正意思,不是之前所说的那么简单,很多描述起来还是跟现实中的一些理解相“矛盾”的,能过老师讲解的几个例子,对面向对象还是有了进一步的了理解:“面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。”这句话我必须理解和深深的记住它。通过这个题目还对线程池和线程的定时器有了进一步的学习和掌握,这些我感觉还是比较简单的,更重要的我认为是线程并发库那块的知识是重点,所以我还需要抽出时间去多学习并发库的知识。另外对自己提出点要求:就是基础部分必须还要再去巩固。因为在看老师的高新技术和这个面试例子时感觉自己有些基础知识还是掌握的不是很牢固,所以还得加强、巩固!为自己加油!
虽然我爱的人离我而去,但是我必须要坚持下去,必须让她看到我的努力不是白费的!!!