交通管理系统
交通管理系统这道题,用面相对象的思想分析,不怎么难。
首先明白车是怎么开的:
一个十字路口,4个方向12条路。其中有4条路可以自由转弯(向右转),其余8条路两两对应(即它绿我绿,它红我红)。其实明白4条路(如图1,2,3,4)就好理解了。
用面向对象来分析,这个场景应该有4个对象,分别是:车,路,红绿灯,灯的控制系统。
仔细分析发现,车能不能过马路,是有红绿灯决定的,这个时候就可以把车,看成马路的内容。这样系统分为三个类,Road(路),Lamp(灯),LampController(灯的控制器)
分析马路:马路有12条,定义一个类,将一条马路的内容封装。那马路有什么内容啊?
(1)马路的名称,
( 2)马路上装车的集合
(3)随机添加的车的方法
(4)当为绿的时减少车的方法
下面为路这个类的代码:
public class Road {
/*步骤:1创建一盒集合用于装车
* 2定义一个名字的构造函数
* 3创建一个随机生产车的线程用executives创建
* 4创建一个线程每一秒检查一下红绿灯,如果为绿删除一个*/
private List<String> vechicles = new ArrayList<String>();
private String name;
public Road(String name) {
super();
this.name = name;
//定义一个线程生产车,
ExecutorService pool= Executors.newSingleThreadExecutor();
pool.execute(new Runnable() {
@Override
public void run() {
// 随机生产车
for(int x=1;x<1000;x++){
try {
//输1到10秒
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//生产这条路上的一辆车。
vechicles.add(Road.this.name +x);//内部内调用外部类类名点this,就可以了
}
}
});
//在定义一个线程判断如果是绿灯就减少一辆车,(每一秒判断一次,定时爆破)
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//判断集合里面有没有车
if(vechicles.size()>0){
// 监控灯的颜色
//判断灯的颜色。通过路的名字判断灯是不是绿的
boolean lighted =Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println( vechicles.remove(0));
}
}}
},
1,
1,
TimeUnit.SECONDS);
}
}
(注意:内部类访问外部类灯的属性,可以用类名.this.属性,方法访问
枚举的valueOf()方法可以将字符串返回为对应灯对象。executors可以开启线程池。)
分析灯:
(1)12条路,那么可以假设有12个灯(每条路定义一个灯,向右转的灯可以定义为常绿)。用枚举可以将12灯的对象固定。
(2)还要明白一个现象即:当前灯亮,对面的灯也要亮。当前灯黑,对面等也要黑,并且下一个可灯要亮。这端话可以提炼出灯的三个参数,对面的灯,下一个灯,和当前灯的亮黑。这样就可以创建一个有参的构造函数。
(3)那么等有哪些方法?
(a)判断灯状态等方法。
(b)当前灯变亮,对面等也变亮
(c)当前灯变黑,对面等也变黑,并且下一个灯变亮。
代码如下
public enum Lamp {
//用枚举定义12灯
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(String opposite, String next ,boolean lighted) {
this.opposite = opposite;
this.Lighted = lighted;
this.Next = next;
}
//定义判断灯绿红的放
public boolean isLighted(){
return Lighted;
}
//定义一个灯亮,让对面亮,
public void light(){
this.Lighted = true;
if(opposite != null){ //这样鞋是为了防止死循环
Lamp.valueOf(opposite).light();
}
System.out.println(name() + " 灯变绿了,6个方向能看到汽车穿过!");
}
//定义一个灯黑,让对面黑,并让下一个亮
public Lamp black(){
this.Lighted=false;
if(opposite!=null){
Lamp.valueOf(opposite).black();
}
Lamp NextLamp =null;
if(Next!=null){
NextLamp=Lamp.valueOf(Next);
System.out.println("绿灯冲"+name()+"切换到"+Next);
NextLamp.light();
}
//返回一个灯,方便调用下一个灯。
return NextLamp;
}
}
分析灯控制系统:
控制系统干两件事:
1. 定义开始时那个灯为绿。
定义每隔多少时间让当前灯变红,下一个灯变绿。
public class LampController {
//定义一个当前灯属性
private Lamp currentLamp;
public LampController() {
// 开始让那个灯亮
currentLamp = Lamp.S2N;
currentLamp.light();
//定义一个线程,每隔10秒让当前灯黑,下一个灯亮。
ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
currentLamp=currentLamp.black();
}
},
1,
10,
TimeUnit.SECONDS);
}
}
最后主函数:创建马路灯对象,并把路名传给对象。开启控制器就可以运行了。
public static void main(String[] args) {
//创建一个数组,存放路名
String[] names = new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S" };
for(int x=0;x<names.length;x++){
new Road(names[x]);
new LampController();
}
总结:交通管理系统这道题,代码看上去很多,但用面相对象灯思路去分析,思路就会很清晰,体现了面向对象思想的好处。以后遇到这种问题,思路清晰,写代码就容易多了。