您的位置:首页 > 职场人生

黑马程序员12——交通灯管理系统

2014-05-10 19:37 225 查看
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! -------------------------------

一、需求:

模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:

异步随机生成按照各个路线行驶的车辆。

   例如:

由南向而来去往北向的车辆 ---- 直行车辆

由西向而来去往南向的车辆 ---- 右转车辆

由东向而来去往南向的车辆 ---- 左转车辆

。。。

信号灯忽略黄灯,只考虑红灯和绿灯。

应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。

二、面向对象的设计分析

1.类的分析

  面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。例如:

火车司机刹车:刹车这个方法是车提供的,刹车动作是刹车系统内部完成的,司机没那么力气是火车停下了,司机发出刹车指令。

人在黑白画圆:画园动作用到 圆心、园半径R ,人画圆圈需要用到这些数据,这些数据是圆提供的,方法再圆上,不应该定义在人身上。

人关门:关门方法是门提供的,门有转轴,轴心转动,转动关门的方法定义在门身上,人只是提供一外力推一下,调用关门的方法。

  1、“两块石头磨成了一把石刀,石刀可以砍树,砍成木头,木头做成椅子”

分析:石头变成石刀,不是自己变成石到,通过其他磨成刀。如石刀加工成,磨刀方法定义在石刀加工场,接收参数(两块石头)

石刀来砍树,有砍树方法 ,木头变成椅子,不是自己变成的,是被加工成使用,变成椅子的方法定义在加工场。

  2、“球从一根绳子的一段移动到另一端”分析其有多少个对象。

分析:绳子,有长度,有两个结束点的坐标。提供一个点到下一个点的方法,球滚动,提供滚动的方法,怎么滚

2.类的功能分析:

a. 要有红绿灯的控制系统,指挥灯的颜色变化。

b.车在这条路上行驶,对应的等是绿色的才通行。其那面还有车,这条路相当于一个集合中有很多车。

c、路线集合中存储的汽车,车会拐弯,穿过、过程增加和减少车辆,减少的方法是路提供,对象是路线 。

d.设计类就需要 1.红绿灯、2.红绿灯控制系统,3.路线(车相当于是路线里面的一个元素) 三个类。

分析 路线:1.总共会有12条路线(南到北有(直走、左拐、右拐),四个方向共12条路线) 即系统中总共要产生12个路线实例对象。

2.每条路线上随机增加新的车辆,把车子增加到一个集合中保存,每条路线每隔一秒都会检查控制本路线的灯是否为绿,

是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。

灯: 1.既然是12条路线,所以,系统中总共要产生12个交通灯。一个灯由绿变红时,应该将下一个方向的灯变绿。右拐弯的路线本来不受灯的控制

2.右拐弯方向的其他8条路线的灯,它们是两两成对的,可以归为4组, 南到北灯是绿的、相对的北到南也是绿的。

所以,只要从这4组中各取出一个灯,对这4个灯依次轮询变亮,与这4个灯方向对应的灯则随之一同变化,因此Lamp类中要有一个变量来记住自己相反方向的灯,、

在一个Lamp对象的变亮和变黑方法中,将对应方向的灯也变亮和变黑。每个灯变黑时,都伴随者下一个灯的变亮,Lamp类中还用一个变量来记住自己的下一个灯。

3.设计灯的控制类,定时让绿灯变红

三编写类:

1.编写路线这个Road 类

分析:1.每条路线都有一个成员变量name属性代表方向路线 List集合存放该方向上的车辆

2.在Road对象的构造方法中启动一个线程每隔一个随机的时间,List集合中增加车辆

3、在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,

是则打印车辆集合和将集合中的第一辆车移除掉

package com.itheima.traffic;

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;

public class Road {

/**

* @Author hutian

*/

//每创建一条路线定义个名字

private String name=null;

// 路线的集合存放路上跑的车

private List<String> list=new ArrayList<String>();

public Road(String name){

this.name=name;

//启动一个线程,每隔一个随机的时间向list 集合中添加一辆车

// 提供一个线程池,产出都是一组线程,池来控制线程,那个空闲调用那个。

ExecutorService pool = Executors.newSingleThreadExecutor()
;

pool.execute(new Runnable(){

@Override

public void run() {

for(int i=1;i<1000;i++){

try {

//1秒到10秒钟内随机会有车经过

Thread.sleep((new Random().nextInt(10)+1)*1000);

} catch (Exception e) {

// TODO: handle exception

}

//内部类访问外部类的成员变量:

list.add(Road.this.name+"_"+i) ;

}

}

});

// 启动一个定时器,每隔一秒检查该方向上的灯是否为绿色,如果是绿灯就放行

ScheduledExecutorService timer = Executors.newScheduledThreadPool(1)
;

timer.scheduleAtFixedRate(new
Runnable(){

@Override

public void run() {

// //该路上的车辆是否大于0,路上有车跑

if(list.size()>0){

//该路上的灯是否为绿;如果为绿则车辆通过路口

//boolean lighted=true;

// 得到路线,确定灯状态

boolean lighted =Lamp.valueOf(Road.this.name).isLighted();

if(lighted){

//返回某个车 状态

System.out.println(list.remove(0)+"is running!");

}

}

}

},
1, 1, TimeUnit.SECONDS);

}

}

2.编写灯Lamp这个类

分析:1.使用枚举形式定义,根据灯的名称就可以获得对应的灯的实例对象。

2.南北向车辆与东西向车辆交替方向,同向等待车辆应该先放行直行车辆

3.每个Lamp对象都有亮、黑的状态,S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮。

定义一个相反方向的灯,下一个变亮的灯,用构造方法进行赋值。

4.定义变亮和变黑的方法light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,

这两个方法内部要让相反方向的灯随之变亮和变黑,(如南往北,北往南相向的灯一致)blackOut方法还要让下一个灯变亮。

5.S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null,

以便防止light和blackOut进入死循环。

package com.itheima.traffic;

public enum Lamp {

/**

* @param args

* 。

*/

//每条路线上对应的灯:true为绿,false为红

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),

//应为向右方向的车不受控制,所以,可以假想它们总是绿灯

S2E(true,null,null),E2N(true,null,null),N2W(true,null,null),W2S(true,null,null);

private Lamp(boolean ligthed,String opposite , String next){

this.ligthed=ligthed;

this.opposite=opposite;

this.next=next;

}

// 设计灯,每条路线上对应的灯:true为绿,false为红灯

private boolean ligthed;

// 定义一个对应灯的变量 如S2N -> N2S

private String opposite;

// 表示此灯变绿后下一个变绿的灯

private String next ;

public static void main(String[] args) {

// TODO Auto-generated method stub

}

//判断灯状态,返回灯

public boolean isLighted(){

return ligthed;

}

//灯变亮的方法

public void light(){

this.ligthed=true;

if(opposite!=null){

((Lamp)
Lamp.valueOf(opposite)).light();//返回枚举对应的名字对象

//opposite.light();
//对应灯

}

System.out.println(name()
+ " lamp is green,下面总共应该有6个方向能看到汽车穿过!");

}

// 灯熄灭变黑

public Lamp blackOut(){

this.ligthed=false;

if(opposite!=null){

Lamp.valueOf(opposite).blackOut();//
灯变黑

}

//我变黑了,要让下个灯变绿

Lamp
nextLamp=null;

if(next!=null){

nextLamp
= Lamp.valueOf(next);

System.out.println(
name()+"变红!" + next +"下个变绿!");

nextLamp.light();

}

return nextLamp;

}

}

3.灯控制系统LampController 类的编写

分析:

  1、整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。

  2、LampController构造方法中要设定第一个为绿的灯。

   3、LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。

package com.itheima.traffic;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

import javax.swing.Timer;

public class LampController {

/**

* @param args

*/

// 当前为绿的灯

private Lamp currentLamp;

public LampController(){

currentLamp=Lamp.S2N;// 南到北

currentLamp.light();//亮

//启动一个定时器:每隔10秒将当前灯变红和下一个灯变绿

ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);

timer.scheduleAtFixedRate(

new Runnable(){

public void run(){

System.out.println("交通运行开始啦!");

currentLamp = currentLamp.blackOut();

}

},

10,//每隔10秒变换

10,

TimeUnit.SECONDS);

}

public static void main(String[] args) {

// TODO Auto-generated method stub

}

}

编写TestTraffic测试

package com.itheima.traffic;

public class TestTraffic {

/**

* @param args

*/

public static void main(String[] args) {

String[] directions = {"S2N","N2S","S2W","N2E","E2W","W2E",

"E2S","W2N","S2E","N2W","E2N","W2S"};

// 1、用for循环创建出代表12条路线的对象。

for(int i = 0 ; i < directions.length ; i ++) {

new Road(directions[i]) ;

}

//获取LampController对象并调用其start方法运行交通系统

new LampController() ;

}

}

打印结果:

N2S lamp is green,下面总共应该有6个方向能看到汽车穿过!

S2N lamp is green,下面总共应该有6个方向能看到汽车穿过!

E2N_1is running!

S2E_1is running!

W2S_1is running!

E2N_2is running!

S2N_1is running!

N2W_1is running!

W2S_2is running!

交通运行开始啦!

S2N变红!S2W下个变绿!

N2E lamp is green,下面总共应该有6个方向能看到汽车穿过!

S2W lamp is green,下面总共应该有6个方向能看到汽车穿过!

S2W_1is running!

N2E_1is running!

E2N_3is running!

N2E_2is running!

N2E_3is running!

S2E_2is running!

E2N_4is running!

S2E_3is running!

S2W_2is running!

N2W_2is running!

S2E_4is running!

S2W_3is running!

W2S_3is running!E2N_5is running!交通运行开始啦!

S2W变红!E2W下个变绿!

W2E lamp is green,下面总共应该有6个方向能看到汽车穿过!

E2W lamp is green,下面总共应该有6个方向能看到汽车穿过!

E2W_1is running!

W2E_1is running!

E2N_6is running!

E2W_2is running!

E2N_7is running!

W2E_2is running!

W2S_4is running!

E2W_3is running!

W2E_3is running!

N2W_3is running!

S2E_5is running!

W2S_5is running!

E2W_4is running!

W2E_4is running!

N2W_4is running!

交通运行开始啦!

总结:主要学会分析思路,没分析清楚是敲不出代码。

1.交通灯管理系统,先分清多少路线,东南西北四个方向,每个方向车都右向左、向右、直行的路线对象是路线,共12条。

2.不是定义车这个对象,不管是摩托车、还是汽车、车始终相当于路线合中的一个元素,路这个对象来控制车,关注的是路线方向。

3.线程管理中,产出都是一组线程,池来控制线程,那个空闲调用那个。

4.右拐弯的方向灯可不计影响看做全部绿灯,因为同一线路上前行灯是绿色通行的话,右方向的即可通行。

面向对象思想:路提供各个方向行驶的方法,谁拥有数据谁提供方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: