黑马程序员 (7k面试) 交通灯程序设计学习总结

来源:互联网 发布:东风(十堰)整合优化 编辑:程序博客网 时间:2024/04/20 21:36

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ------------------------

面向对象的思想,要想将事物封装对象。根据谁拥有数据,谁就是专家的方法。可以将系统内的事物,封装成
 * 三的对象:路Road;灯Lamp;控制系统ControllorLamp。
 * 
 * 类Lamp的设计
 * 经过分析,可以知道十字路口总共有12条,其中有四对路线是并发,同时这四对路线又是互斥的。另外四条
 * 路线是不受到交通灯控制的。
 * 四对并发互斥路线:
 * S2N N2S;S2W N2E;E2W W2E;E2S W2N
 * 灯亮依次调用的顺序可为:
 * N2S-->N2E-->E2W-->E2S--
   |-----------<----------------------|
 *不断的循环
 * 
 * 四条不受交通灯控制的路线为:
 * S2E ; E2N; N2W ; W2S;
 * 因此灯的实例对象其实只有12个,这样的话,该类使用枚举是最好的。
 * 灯这个类,应该包含下类属性和函数
 * 属性:
 * private  boolean  lighted  :是否灯是亮的,true:绿灯,false:红灯
 * private  Lamp     opposite : 与当前灯并发的灯
 * private  Lamp     nextLamp : 该灯的下一个灯
 * 
 * 构造方法
 * Lamp(String opposite,String nextLamp,boolean lighted):接受三个参数
 * 
 * 主要方法
 * boolean  isLighted()  返回当前灯的显示红绿灯情况
 * void     light()      使当前灯亮,并使当前灯的并发灯也亮(如果有)
 * Lamp     blackOut()   使当前灯和其并发灯(如果有)熄灭,并使当前灯的下一个灯(如果有)亮。

public enum Lamp {
//本来构造方法中,应该传入的是Lamp对象,但是,因为编译器的语法问题,不能在没创建对象之前就
//使用了该对象,所以就需要将传入将来的对象改为传入字符串(对象名称),再在方法中使用enum的
//静态方法valueOf,将其转化为对象。
N2S("S2N","N2E",false),N2E("S2W","E2W",false),E2W("W2E","E2S",false),E2S("W2N","N2S",false),
S2N(null,null,false),S2W(null,null,false),W2E(null,null,false),W2N(null,null,false),
N2W(null,null,true),W2S(null,null,true),S2E(null,null,true),E2N(null,null,true);

private String opposite = null;
private String nextLamp = null;
private boolean lighted = false;

private Lamp(String opposite,String nextLamp,boolean lighted){
this.opposite = opposite;
this.nextLamp = nextLamp;
this.lighted = lighted;
}

public String getOpposite() {
return opposite;
}

public boolean isLighted(){
return this.lighted;
}

public void light(){
this.lighted = true;
if(this.opposite != null){
Lamp oppositeLamp = Lamp.valueOf(opposite);
oppositeLamp.light();

}
}

public Lamp blackOut(){
this.lighted = false;
if(this.opposite != null){
Lamp oppositeLamp = Lamp.valueOf(opposite);
oppositeLamp.blackOut();
}
Lamp nextLamp = null;
if(this.nextLamp != null){
nextLamp = Lamp.valueOf(this.nextLamp);
System.out.println("绿灯由[ "+name()+"]转移到了["+nextLamp.name()+"]了");
nextLamp.light();
System.out.println(nextLamp.name() + ":是绿灯了"+"::"+nextLamp.getOpposite()+":是绿灯了");
return nextLamp;
}
return nextLamp;
}
}

* 创建Road类
 * 路会随机产生12个方向的车,而12方向的路就应该是12个路的实例对象。
 * 路一创建就需要产生两个线程,就需要在构造函数中调用方法,同时需要使用jdk1.5中创建线程的新技术
 * 
 * 一个线程是随机获取道路上的车辆,并将等待的车辆
 * 储存在集合中;
 * 另外的一个线程则用来每隔一秒钟判断该路的绿灯是否亮,如果亮了,就将集合中的第一个元素
 * 从集合中取出。
 * 
 *属性
 *Lamp  lamp   :用来获取道路路线的名称和控制该道路的信号灯
 *List<String>  ArrayList :存储获取的汽车
 *  
 * 构造方法
 * Road(String lampName) :用来获取该道路的名称,并将名称装换为控制该路线信号灯的Lamp对象。
 * 
 * 主要方法:
 * private  void   gainVehicle()  :用来增加交通工具
 * private  void   isMoveVehicle()  :用来判断是否有车等待,如果有车等待则看看该条路线是否为绿灯。
 * 
 * */
public class Road {
Lamp lamp = null;
List<String> vehicles = new ArrayList<String>();

public Road(String lampName){
lamp = Lamp.valueOf(lampName);
gainVehicle();
isMoveVehicle();
}
public void gainVehicle(){
ExecutorService pool =  Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){
public void run(){
for(int i =1 ;i <100;i++){
try {
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
vehicles.add(Road.this.lamp+"_"+i);//内部类访问外部变量使用格式为Road.this.lamp
}
}
});

}
public void isMoveVehicle(){
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(vehicles.size()!= 0){

if(Road.this.lamp.isLighted()){
System.out.println(vehicles.remove(0)+ " is traversing!");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}

/*定义一个控制信号灯的类,其构造函数接受一个字符串,该字符串可以转化为一个Lamp对象
 * 并将该对象作为信号灯的第一个变绿的绿灯,同时创建一个线程,每个一段时间就将当前
 * 型号灯变为红灯,并将自己对应的下一个型号灯变为绿灯。
 * 使用的是一个新的创建线程的方式
 * 创建线程不需要定时,书写格式
 * ExecutorService pool =  Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){public void run(){}});
 * 使用Executors类的静态方法newSingleThreadExecutor(int arg)创建一个线程,
 * 调用该对象的execute方法并常见一个Runnable的子类
 * 
 * 创建线程需要定时,反复执行
 * ScheduledExecutorService  pool = Executors.newScheduledThreadPool(1);//1表示设置这个线程池中只有一个线程
pool.scheduleAtFixedRate(
new Runnable(){public void run(){}}, 
10,//当程序启动后,隔多长时间执行该run方法
10,//隔多长时间再次执行run方法
TimeUnit.SECONDS);//设置前面两个参数的时间单位是什么。
  预定可执行服务的对象 pool方法scheduleAtFixedRate()方法中要接受三个参数。
 * */
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 CntrlLamp {
private Lamp currentLamp = null;


public CntrlLamp(String currentLamp){
this.currentLamp = Lamp.valueOf(currentLamp);
this.currentLamp.light();
System.out.println(this.currentLamp + " 是绿灯了!");
System.out.println(this.currentLamp.getOpposite() + " 是绿灯了!");
 
ScheduledExecutorService  lampCtrl = Executors.newScheduledThreadPool(1);
lampCtrl.scheduleAtFixedRate(
new Runnable(){
public void run(){
CntrlLamp.this.currentLamp = 
CntrlLamp.this.currentLamp.blackOut();
}
}, 
10,
10,
TimeUnit.SECONDS);
}
}

该程序总的流程是:控制信号灯对象每隔一段时间就调用信号灯类中的方法,将信号灯按照一定规律循环变换

                                    另一边,路类就不断的增加各个路线上的车辆,同时每个一段时间,各个路线上的路对象就

                                    判断一下该路线的型号灯是否为绿灯。如果为绿灯就放行一辆车。



-------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

0 0
原创粉丝点击