• JAVA学习之交通灯管理系统分析与实现


     

    交通灯管理系统:

    需求:
    模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
    1. 异步随机生成按照各个路线行驶的车辆。
    例如:
    由南向而来去往北向的车辆 ---- 直行车辆
    由西向而来去往南向的车辆 ---- 右转车辆
    由东向而来去往南向的车辆 ---- 左转车辆
    。。。
    2. 信号灯忽略黄灯,只考虑红灯和绿灯。
    3. 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
    4. 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
    注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
    5. 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
    6. 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
    7. 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

    我们先分析业务逻辑.系统要求的是十字路口,每一个路口的第一辆车都有三种走法,
    第一种是右拐
    第二种是直行
    第三种是左拐
    即有三种路线,每个路口三种,十字路口有4个路口,一起有3*4=12种路线,要求通过对这12条路线的控制,实现对对应路线上车辆放行的功能
    又联系实际,不考虑特殊情况下的线路走法,是南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。并且,所以路口的右转车辆可以一直通行,不用等待

    比如在一个路口上:直行的先走,然后到左拐的,右拐的不用等就直接走.
    所以要求系统中有一个和路线一样功能的类,即路线类,这个类的主要功能是走车,走各个方向的车,而且路线上的车是随机的,有可能是直行,右拐,左拐,无论什么车,通过时间都是一秒.
    再由于路线上的车是走还是等待,是由于信号灯控制的,所以还必须有一个和信号灯功能一样的类,但是右拐的车是一直都可以走的,是没有信号灯控制的.而且信号灯还有变红变绿的功能.(黄灯忽略)
    还有信号灯不是一开始就亮的,也不是自己就会变红变绿的,所以还得有一个信号灯控制功能的类,可以实现在时间间隔内交替的将信号灯变红变绿.
    业务分析好了,下面开始代码实现;
    由于在这里路线和信号灯控制器都要依赖于信号灯,而信号灯是业务独立的,所以为了好理解,我们可以先实现信号灯功能的类.

    分析可见,12条路线中,所有的右拐车辆是不受信号灯控制的,但是为了模型统一,我们可以假设所有的右拐车辆也是受信号灯控制的,只不过是信号灯用的是不会灭的绿灯而已.
    然后直行的线路中,它的信号灯和对头的信号灯总是状态是一样的,比如有一个南向北的信号灯,那么这个信号灯和北向南的信号灯的状态是一样的,同时绿,同时红,
    还有就是直行的灯的信号总是和它左拐的灯的信号是相反的,而且是直行先走,然后直行的灯变红了,左拐的灯就会变绿,因为灯的功能是差不多一样的,而且为了使用方便,我们可以用JAVA的新特性--枚举来实现.枚举是一种特殊的(类).因为既有方法,字段,也有构造方法
    代码实现如下:

    //
    package com.fylx.test;
    public enum Lamp
    {
        // 直行线路的信号灯,直行灯亮完之后,左拐的灯再亮,左拐的灯变红之后,另一个直行的灯变亮
        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 String nextlamp;
        private boolean isGreen;
    
        // 返回一个灯是否是绿色的属性
        public boolean isGrean()
        {
            return this.isGreen;
        }
    
        // 每个信号灯的对头灯,下一个要变绿的灯,这个灯是否绿色的
        Lamp(String opposite, String nextlamp, boolean isGreen)
        {
            this.opposite = opposite;
            this.nextlamp = nextlamp;
            this.isGreen = isGreen;
        }
    
        // 变绿的方法,如果有对头灯,对头灯的状态也要变绿
        public void turnGrean()
        {
            this.isGreen = true;
            System.out.println(this.name() + "方向的灯变绿了!");
            if (this.opposite != null)
            {
                Lamp.valueOf(this.opposite).turnGrean();
            }
        }
    
        // 变红的方法,如果有下一个对应的灯,则下一个灯要就绿,同时返回下一个灯
        public Lamp turnRed()
        {
            this.isGreen = false;
            System.out.println(this.name() + "方向的灯变红了!");
            if (this.opposite != null)
            {
                Lamp.valueOf(this.opposite).turnRed();
            }
            Lamp next = null;
            if (this.nextlamp != null)
            {
                next = Lamp.valueOf(this.nextlamp);
                Lamp.valueOf(this.nextlamp).turnGrean();
            }
            return next;
        }
    }
    //

    下面我们我分析信号灯的控制器,由需求可以看出,控制器就是控制信号灯的交换时间的,只要弄一个定时器,在规定的时间和时间间隔内不断的让信号灯有条理的亮起来了变换就可以了
    而且从上面的信号灯中我们可以看出,信号灯在变换的时候,会自动的触发其对应的对面的信号灯和左拐灯的变化,所以,在控制器中,我们只要控制一个灯的变红变绿就可以了,
    代码实现如下:

    //
    package com.fylx.test;
    import java.util.concurrent.*;
    public class Controller
    {
        //控制器当前要控制的信号灯
        private Lamp currentLamp;
    
        public Controller()
        {
            this.currentLamp = Lamp.S2N;
        }
    
        // 启用信号灯控制器,5秒后执行,并每过10秒变换信号灯的颜色
        public void on()
        {
            this.currentLamp.turnGrean();
    
            ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
            timer.scheduleAtFixedRate(new Runnable()
            {
                public void run()
                {
                    currentLamp = Controller.this.currentLamp.turnRed();
                }
            }, 5, 10, TimeUnit.SECONDS);
        }
    }
    //

    路线类的分析,由需求可知,路线类只管按信号灯的变化走车,车的增加和出现是异步随机生成的.且每辆车通过路口的时候都为1秒,能不能走车就看对应的信号灯是不是绿灯,而且路线的功能
    与信号灯控制器没有关联,而于之关联的是信号灯,由于我们的信号灯是用枚举实现的,所以路线类直接保存信号灯的名称就可以了,由于路线上有车,所以路线这个类中也要添加相关车的代码
    代码实现如下:

    //
    package com.fylx.test;
    import java.util.*;
    import java.util.concurrent.*;
    
    public class Route
    {
        // 定义一个交通工具
        private List<String> vechicles = new ArrayList<String>();
        // 线路的名称,要求和信号灯的名称对应
        private String name;
        // 随机算算器
        Random random = new Random();
    
        public Route(String name)
        {
            this.name = name;
            // 启动一个线程池,异步随机的生产交通工具
            ExecutorService service = Executors.newSingleThreadExecutor();
            service.execute(new Runnable()
            {
                public void run()
                {
                    for (int i = 1; i < 1000; i++)
                    {
                        try
                        {
                            Thread.sleep((random.nextInt(10) + 1) * 1000);
                        } catch (InterruptedException e)
                        {
                            e.printStackTrace();
                        }
                        Route.this.vechicles.add(Route.this.name + "_" + i);
                    }
                }
            });
            // 定义定时器,在1秒后执行,并且每1秒过一辆车
            ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
            timer.scheduleAtFixedRate(new Runnable()
            {
                public void run()
                {
                    if (vechicles.size() > 0)
                    {
                        Lamp lamp = Lamp.valueOf(Route.this.name);
                        if (lamp.isGrean())
                        {
                            System.out.println(vechicles.remove(0) + "安全通过了!");
                        }
                    }
                }
            }, 1, 1, TimeUnit.SECONDS);
    
        }
    }
    //

    现在我们来模拟一个测试环境,在这个环境中,有路线,有信号灯控制器,因为信号灯是枚举,不用在这里实例化,直接在控制器里面关联一个信号灯就可以了.
    测试代码如下:

    //
    package com.fylx.test;
    public class Test
    {
        public static void main(String[] args)
        {
            // TODO Auto-generated method stub
            String[] lamps = new String[] { "S2N", "S2W", "E2W", "E2S", "N2S", "N2E", "W2E", "W2N", "S2E", "E2N", "N2W", "W2S" };
    
            for (String lamp : lamps)
            {
                // 根据信号灯,实例化对应的线路
                new Route(lamp);
            }
            // 生产一个信号灯控制器,并同时启用
            new Controller().on();
        }
    }
    //

    在这个系统的设计过程中,难的并不是代码实现,而是业务分析,如果业务逻辑分析清楚了,代码实现也就好写了.

  • 相关阅读:
    JS 使用 html2canvas 将页面转PDF
    代码记录
    js 原生图片批量上传 multiple="multiple"
    Go中的HTTP debug技能
    位运算 交换2个数 异或运算
    记一次 JMeter 压测 HTTPS 性能问题 拂衣 阿里云云栖号 20220527 19:00 发表于北京
    RVA relative virtual address PE
    进制
    浏览器是不允许页面直接读取本地硬盘资源的
    四平方和定理
  • 原文地址:https://www.cnblogs.com/fylx/p/3964263.html
Copyright © 2020-2023  润新知