class Rope { private Point start; private Point end; public Rope(Point start,Point end) { this.start = start; this.end = end; } //获取下一个点的方法 public Point nextPoint(Point currentPoint) { } } class Ball { private Rope rope; private Point currentPoint; public Ball(Rope rope,Point currentPoint) { this.rope = rope; this.currentPoint = currentPoint; } //小球的移动方法 public void move() { currentPoint = rope.nextPoint(currentPoint); } }
class KnifeFactory { private Stone stone; public KnifeFactory(Stone stone) { this.stone = stone; } //生产刀的方法 public Knife creatKnife(Stone first,Stone second) { .... return kinfe; } }
二,7K面试题之交通灯管理系统
交通灯管理系统
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
Ø 异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
Ø 信号灯忽略黄灯,只考虑红灯和绿灯。
Ø 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
Ø 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
Ø 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
Ø 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
以面向对象的思维初步分析这道题:
直接从题目表面上看起来,应该要用到的对象有:红绿灯,红绿灯的控制系统,汽车,路线。
汽车是否穿过路口,要看前面是否有车,应该问谁前面是不是有车呢?是路,路中存储着车辆的集合,所以路上应该有增加和减少车辆的方法。所以只要捕捉出车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,而车不需要单独作为一个对象,用一个字符串表示即可。 这样以来,正真要我们定义的类应该就只有:交通灯,交通灯控制器,路。
首先,画出路线图:
1,首先定义一个Road类,每个Road对象代表一条路线,一共有12条路线,所以系统中要创建12个Road的实例对象。
每条路线上随机增加车子,车子用一个字符串代替,将车子存储到集合中。每条路线每隔1秒检查路灯是不是为绿,如果集合中有车子,则从中移除一辆车子。详细过程见注释。
package com.yue.lamp; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /* * 每条路线上都会有来来往往的车子,使用面向对象的原理,车子在路口等待和行走,其实就是路线在增加和删除车子, * 通过集合存储过来的车子。异步随机生成各个路线的来往车辆,可以使用jdk1.5里面的线程机制,通过创建单一线程池 * 模拟车子不断增加过程。通过创建调度线程池,模拟车子通过路口。详细分析见注释。 */ public class Road { //创建交通工具集合,存储本路线过来的车子 private List<String> vehicles/*交通工具*/ = new ArrayList<>(); //使用字符串来标记车子,向集合中增加车子就是增加一个字符串 private String name = ""; public Road(String name) { this.name = name; /*模拟路线上增加车子的情况 * 创建线程池,向线程池中添加随机时间增加车子的任务,并由线程池中的一个线程执行该任务. */ ExecutorService pool = Executors.newFixedThreadPool(1); pool.execute(new Runnable() { @Override public void run() { for(int i=0;i<1000;i++) { try { //每隔1到10秒钟(改时间随机生成),增加一辆车子,一共增加1000辆车子 Thread.sleep((new Random().nextInt(10) + 1) * 1000); } catch (InterruptedException e) { e.printStackTrace(); } vehicles.add(Road.this.name + "路线上的车子" + i); } } }); /* * 模拟车子通过路口,当该路线的交通灯变绿则让车子通过。 * 题目要求每辆车穿过路口的时间是1秒钟,可以通过一个定时器,每隔1秒钟检查一下交通灯, * 如果为绿则从集合中减少一辆车子。 */ ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); timer.scheduleAtFixedRate( new Runnable() { @Override public void run() { //如果路口有车子在等待,判断灯是不是为绿 if(vehicles.size() > 0) { boolean lighte = Lamp.valueOf(Road.this.name).islighte(); if(lighte) { //交通灯变绿时每隔一秒移除路口的第一辆车 System.out.println(vehicles.remove(0) + "通过路口"); } } } }, 1, 1, TimeUnit.SECONDS); } }
package com.yue.lamp; /*一共有12条路线,必须要有12个交通灯,来控制车辆是不是通行。因为右转的车子是没有限制的,我们也给这四条路线各定义一个 灯,并且该灯是常绿的。 */ public enum Lamp { /*南北方向东西方向的车交替放行,同一方向的等待车辆先放直行,然后放左转车辆。所以只需要考虑 * 南北走向一个方向的路线和东西走向的一个方向的路线的交通灯情况,也就是4个灯,之后的其余的灯 * 也按照这个模式方向就行了。 * * 同一路线先放行直行车辆,后放行左转车辆,所以同一走向应该同时放行两条相反直行路线,比如:南到北放行时,北到南的 * 直行也在这时候放行。直行结束后,放行该路线的左转路线,该左转路线的相反方向也就是该直行路线的相反方向的左转路线。 * 南到北路线的左转路线是南到西,南到西的相反路线就是北到东,以此类推。当南到北有相反方向路线时,北到南就没有相反 * 方向了。所以每个灯除了要有状态,还要有相反路线的灯,下一个方向的灯。 * */ S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","N2S"), N2S(false,null,null),N2E(false,null,null),W2E(false,null,null),W2N(false,null,null), //4条右转路线的交通灯,状态常绿,没有相反方向的灯和下一个灯的规定 S2E(true,null,null),E2N(true,null,null),N2W(true,null,null),W2S(true,null,null); //每个交通灯要有自己的状态,因为只考虑绿灯和红灯,使用布尔类型变量,灯亮(true)表示绿灯,灯黑(false)表示红灯 private boolean state; private String oppoiste = ""; private String next = ""; //枚举的构造函数 private Lamp(boolean state,String opposite,String next) { this.state = state; this.oppoiste = opposite; this.next = next; } //判断灯的状态 public boolean islighte() { return state; } //某一路线的灯变亮时,并让与自己相反方向的灯也变亮。让自己相反方向的灯变来亮的前提是必须存在下一个灯 public void light() { this.state = true; if(oppoiste != null) { Lamp.valueOf(oppoiste).light(); } System.out.println(name() + "方向的灯变绿了,应该有6个方向的车开始行驶了"); } /*某一路线的灯变黑时,它相反方向的灯也变黑,前提是要有相反方向的灯。 * 并且让下一个灯变亮,前提也是存在下一个灯。下一个灯变亮后,返回下一个灯。 */ public Lamp toBlack() { this.state = false; if(oppoiste != null) { Lamp.valueOf(oppoiste).toBlack(); } Lamp nextLamp = null; if(next != null) { nextLamp = Lamp.valueOf(next); System.out.println("绿灯由" + name() + "切换为:" + next); nextLamp.light(); } return nextLamp; } }
package com.yue.lamp; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /* * 定义一个交通灯的控制器,控制红绿灯交换时间。可以让每隔红绿灯的交换时间为固定的10秒。 * 创建方法还是使用定时器,也就是一个可以在指定时间后执行指定的任务,并且后续可以周期执行该任务的线程池,调用 * schedule()方法,传入任务和时间,周期,时间的单位 */ public class LampController { //先拿到当前的灯 private Lamp currentLamp; public LampController() { currentLamp = Lamp.S2N; //让当前灯变亮 currentLamp.light(); ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); //每隔10秒将当前灯变黑,并将当前灯的下一个灯变绿 timer.scheduleAtFixedRate( new Runnable() { @Override public void run() { currentLamp.toBlack(); } }, 10, 10, TimeUnit.SECONDS); } }
package com.yue.lamp; public class MainClass { public static void main(String[] args) { //创建12条路线数组,使用数组简化书写 String[] name = {"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"}; for(int i=0;i<name.length;i++) { new Road(name[i]); } new LampController(); } }