模拟交通灯管理系统逻辑设计
本文是基于张孝祥Java视频做的总结,本人新手,不喜勿喷
需求
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
分析
涉及到的对象有:车辆、交通灯、交通灯控制器、以及路线。
由于是模拟交通灯管理逻辑,我们可以用字符串代替车辆来模拟这个过程
车是否通过路口是通过交通灯决定的,所以每个路线对应一个交通灯,为了统一编程,右转路线也加入交通灯,只不过状态一直为绿灯即可
这样就有12条线路,对应12个交通灯
下面我们来看路口通行图示
可以看到画相同线条的路线上的交通灯其实是同步的,由南向北与由北向南的灯应该同时绿,同时红,又由于右转灯维护为常绿,所以,需要交通灯控制器控制的灯,其实只有4个,分别是图中标注1,2,3,4的4条路线上的灯
面向对象设计
交通灯Lamp类设计:
由于交通灯是贯穿整个逻辑的,同时又只存在12个灯的实例对象,所以我们可以设计成枚举
内部维护自己的红绿状态
对外提供改变自己与对应灯状态的方法
路线Road类设计:
每条路线需要有一个自己的名字来注明自己具体是哪条路线
内部还需要维护一个集合类来存放车辆,这里车辆用字符串名称来模拟
运行过程中通过一个定时器每隔一秒来判断自己路线上的灯是否为绿,为绿,则放行,为红,则等待
交通灯管理器LampControler类设计:
内部维护一个迭代器代表路口当前可通行的灯,通过定时器每隔固定时间改变当前灯的状态,并获取下一组灯,使之变绿
实现
Lamp类
1: public enum Lamp {
2: /**
3: * | N |
4: * | |
5: * | |
6: * | |
7: * | |
8: * ------------------ ------------------
9: *
10: * W E
11: *
12: * ------------------ ------------------
13: * | |
14: * | |
15: * | |
16: * | |
17: * | S |
18: * */
19:
20: //表示12个路线上的灯
21: S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
22: N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),
23: S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);
24:
25: //对应方向的灯
26: private String oppsite;
27: //下一个需要亮的灯
28: private String next;
29: //当前状态,true表示为绿
30: private boolean light;
31:
32: Lamp(String oppsite,String next,boolean light){
33: this.oppsite = oppsite;
34: this.next = next;
35: this.light = light;
36: }
37:
38: //lightUp表示亮起绿灯
39: public void lightUp(){
40:
41: light = true;
42: System.out.println(name()+ " 绿灯亮了");
43: //如果对应灯非空,则同时改变对应方向灯的状态
44: if(oppsite != null)
45: Lamp.valueOf(oppsite).lightUp();
46: }
47:
48: //lightDown表示亮起红灯
49: public Lamp lightDown(){
50: light = false;
51: System.out.println(name()+ " 红灯亮了");
52:
53: //如果对应灯非空,则同时改变对应方向灯的状态
54: if(oppsite != null)
55: Lamp.valueOf(oppsite).lightDown();
56: //返回下一个方向上的灯
57: if(next != null)
58: return Lamp.valueOf(next);
59: return null;
60: }
61:
62: //获得当前状态
63: public boolean isLight(){
64: return light;
65: }
66: }
LampControler类
1: public class LampControler {
2: //表示循环控制的第一个灯,也为当前灯
3: Lamp currentLamp = Lamp.S2N;
4:
5: //提供开始交通灯控制的方法
6: public void start(){
7:
8: //当前灯亮绿灯
9: currentLamp.lightUp();
10:
11: //定时器
12: ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
13:
14: //每隔10秒改变灯的状态
15: timer.scheduleAtFixedRate(
16: new Runnable(){
17: public void run(){
18: //当前灯变暗,并获得下一组灯的引用
19: currentLamp = currentLamp.lightDown();
20: //下一组灯亮绿灯
21: currentLamp.lightUp();
22: }
23: },
24: 10,
25: 10,
26: TimeUnit.SECONDS);
27: }
28: }
Road类
1: public class Road {
2:
3: //路线名称
4: private String name;
5: //存放车辆的集合
6: private List<String> vechicles = new LinkedList<String>();
7:
8: public Road(String name){
9: this.name = name;
10:
11: //开一个线程池,每隔1-5秒产生一辆车
12: ExecutorService pool = Executors.newSingleThreadExecutor();
13:
14: pool.execute(new Runnable(){
15: public void run(){
16: for(int i = 0 ; i < 1000 ; i ++){
17: try {
18: Thread.sleep((new Random().nextInt(5)+1)*1000);
19: } catch (InterruptedException e) {
20: // TODO Auto-generated catch block
21: e.printStackTrace();
22: }
23: vechicles.add(Road.this.name+"_"+i);
24: }
25: }
26: });
27:
28: //定时器
29: ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
30: //每隔一秒判断一次当前路线上灯的状态
31: timer.scheduleAtFixedRate(
32: new Runnable(){
33: public void run(){
34: //如果当前路线上有车
35: if(vechicles.size() > 0){
36: //如果当前灯是绿灯
37: if(Lamp.valueOf(Road.this.name).isLight()){
38: //则通过一辆车
39: String car = vechicles.remove(0);
40: System.out.println(car+" has passed");
41: }
42: }
43: }
44: },
45: 1,
46: 1,
47: TimeUnit.SECONDS);
48: }
49: }
测试类
1: public class MainClass {
2:
3: /**
4: * @param args
5: */
6: public static void main(String[] args) {
7: //控制器开始工作
8: new LampControler().start();
9:
10: //创建12条路线实例
11: Lamp[] lamps = Lamp.values();
12: for(int i = 0 ; i < lamps.length ; i ++){
13: new Road(lamps[i].name());
14: }
15: }
16: }
总结
再次声明,这是张孝祥老师视频的项目总结,上面实现过程基本是照抄的老师的代码
由于还没有看设计模式,所以很多想法实现起来非常复杂,等以后深入了,再放上自己的代码
总结下这个实现的利弊吧
优点:
思路非常清晰,逻辑简单明了,用来模拟一个逻辑是够用了
不足:
因为只是个逻辑,所有感觉程序扩展性不强,等以后深入了设计模式,会放上自己的框架
现在对设计模式的理解只有一条原则,就是开放封闭原则
即:对扩展开放,对修改封闭