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

------------------ android培训java培训、期待与您交流! ---------------------

一、需求分析:

     每条路都有 直走,左转弯,右转弯三个路线,所以东西南北四条路总共有12条路线。

   由于,相对的两个路口,红绿灯应该是一致的,并且右转弯不需要红路灯控制,相当于常绿。

   因此,可以将问题简化成不想对的两条路、四个路线的问题。比如,南和东的直走和左转弯的路线问题。

 二、面向对象的分析与设计

1、对象:红绿灯,红绿灯的控制系统,汽车,路线。

2、思路分析:

   各个路线上的汽车,首先看该路线上的红绿灯状况,如果为绿,再看自己前面是不是有其他车辆,如果没有,那么这辆车就可以通过路口了。那么,路线中应该存储车辆集合,并且有对车辆的增加和减少的功能。

      另外,我们只是捕获车辆过路口的过程,并不研究车辆移动过程,所以车辆不需要单独设计成一个对象,用一个字符表示就行了。

3红绿灯Lamp

      可以用枚举来定义十二个灯。灯有绿灯green()、红灯red()方法。一个灯,如果它是绿灯,那么它相对的灯也应该变绿。如果它变红了,那么它对面的灯也要变红,并且它的下一个灯要变绿。注意右转弯的灯始终是绿的。

4红绿灯的控制系统LampControl

     要定义一个定时器,每隔十秒钟变换一下灯的红绿。首先初始化一个路线的灯为绿灯,然后定时调用当前灯的红灯red方法,并且返回下一个灯为当前灯,这样才能往复循环。所以Lamp类中的red方法要返回当前等的下一个灯。

5路线Road

     每条的路线都有一个初始化的名称,这个名称和各个路线的红绿的最好对应。每条路要随机生成若干辆车,比如1000辆。也要定义一个定时器,用于每隔一秒钟观察一下自己线路上的红绿的灯,如果是绿灯就通过车辆。

6、测试类TrafficTest创建十二条路线,并且初始化红绿灯的控制系统。

三、代码实现:

1、红绿灯Lamp

public enum Lamp {
	//只有这四个是含有逻辑的灯,控制了这四个灯,对应的就控制了。
	S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
	//下面四个灯是上面四个灯的对面opposite,受上面灯的控制,这些灯的opposite为null,以防死循环
	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 next;
	//如果lighted为true则为绿灯
	private boolean lighted;
	private Lamp(){}
	private Lamp(String opposite,String next,boolean lighted){
		this.opposite = opposite;
		this.next = next;
		this.lighted = lighted;
	}
	
	public boolean isLighted(){
		return lighted;
	}
	
	//让灯变绿灯的方法,如果这个灯变绿了,那么它对面的灯也要变成绿灯
	public void green(){
		this.lighted = true;
		System.out.println(name()+"is changed Green,下面六个路线的车辆可以行走");
		if(opposite != null){
			Lamp.valueOf(opposite).green();
		}
	}
	//让灯变红灯,如果这个灯变成红灯,那么它对面的灯也变成红灯,且它的下一个灯next变成绿灯
	public Lamp red(){
		this.lighted = false;
		//先让自己变红
		if(opposite != null){
			Lamp.valueOf(opposite).red();
		}
		//紧接着让下一个变绿,
		
		Lamp nextLamp = null;
		if(next != null){
			nextLamp = Lamp.valueOf(next);
			System.out.println(name()+"的下一个路口切换成绿灯了");
			nextLamp.green();
			
		}
		return nextLamp;
	}
}
2、红绿灯的控制系统 LampControl
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * 这是一个红绿灯控制器,实现每隔十秒钟,切换成下一个路口的灯变绿
 * */
public class LampController {
	//声明一个当前灯currentLamp
	private Lamp currentLamp;
	public LampController(){
		currentLamp = Lamp.S2N;
		//刚开始就让当前的灯变绿
		currentLamp.green();
		//然后定义一个定时器,每隔十秒钟当前灯变红,并且下一个灯变绿
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				System.out.println("红绿灯切换");
				//每隔10s调用red方法让当前的灯变红,当前的下一个灯变绿,并且要返回当前灯的下一个,如果不返回,当前灯将永远是S2N
				currentLamp = currentLamp.red();
			}
		}, 
		10,
		10,
		TimeUnit.SECONDS);
	}
}
3、路线 Road
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class Road {
	private List<String> vehicles = new ArrayList<String>();//使用List是面向接口编程
	private String name;
	public Road(String name){
		this.name = name;
		//模拟车辆不断随机上路的过程
		ExecutorService pool = Executors.newSingleThreadExecutor();
		pool.execute(new Runnable(){
			@Override
			public void run() {
				for(int i = 0; i < 1000;i++){
					try {
						//随机睡1-10s然后增加车辆,相当于随机生成车辆上路
						Thread.sleep((new Random().nextInt(10)+1)*1000);//随机生成1-10,还可以使用Math.random()*10+1查一下
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					vehicles.add(Road.this.name+"这条路上的第"+(i+1)+"辆车!");
				}
			}});
		//每隔一秒钟 检查一下该路线上的红绿灯,绿灯就过
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				if(vehicles.size()>0){
					boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
					if(lighted){
						System.out.println(vehicles.remove(0) + " is traversing !");
					}
				}
				
			}
		},
				1, 
				1,
				TimeUnit.SECONDS);
	}
}
4、测试类 TrafficTest
public class TrafficTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*产生12个方向的路线*/		
		String [] directions = new String[]{
				"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"		
		};
		for(int i=0;i<directions.length;i++){
			new Road(directions[i]);
		}
		
		/*产生整个交通灯系统*/		
		new LampController();
	}

}

四、面向对象设计的重要经验:

谁拥有数据,谁就对外提供操作这些数据的方法。

1、几个例子

*人在黑板上画圆:对象有人、黑板、圆。画圆的方法是圆拥有的,用到它自身拥有的圆心和半径。

*列车司机紧急刹车:对象有列车、司机。刹车的方法是列车的。

*售货员统计收货小票的金额:对象有售货员、小票。统计金额的方法是小票的方法。

*你把门关上:对象有人、门。关门的方法是门的方法,门拥有转动轴。

2、两个面向对象的面试题,用面向对象的方式设计如下情景。

*球从一根绳子的一端移动到了另一端。

对象:球、绳子。球有一个移动的方法,按照某个坐标移动。

*两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子。

对象:石头,石刀,树,木材,椅子。石刀工厂,木材厂,椅子厂。

石刀工厂:将两块石头返回一个石刀。

木材厂:将树返回木材。

椅子厂:将木材返回椅子。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值