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

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

交通灯管理系统

面向对象设计思想:

例题:

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

用面向对象的思想模拟

如下:

对象有:

           石头:Stone

           石刀:StoneKnife

           木材:Wood

           椅子:Chair

                   两块石头磨成一把刀,则就是一个工厂类,传入两块石头做参数,返回一把石刀

        StoneKnifeFactory

           木材做成椅子也是一个工厂类,将木材作为参数,返回一把椅子

ChairFactory

代码如下:

StoneKnife

public class StoneKnife {

	private Stone s1;
	private Stone s2;

	// 石刀由两块石头磨成
	public StoneKnife(Stone s1, Stone s2) {
		this.s1 = s1;
		this.s2 = s2;
	}

	// 石刀有砍树的功能
	public Wood cutTree() {
		return new Wood();
	}
}

Chair

public class Chair {

	// 椅子由木材做成
	private Wood w;
	public Chair(Wood w) {
		this.w = w;
	}
}
    StoneKnifeFactory

public class StoneKnifeFactory {

	public static StoneKnife creatStoneKnife(Stone s1,Stone s2){
		return new StoneKnife(s1,s2);
	}
}
ChairFactory

public class ChairFactory {

	public static Chair creatChair(Wood w){
		return new Chair(w);
	}
}

模拟流程:


public class TestDemo {

	public static void main(String[] args) {
		// 创建两块石头
		Stone s1 = new Stone();
		Stone s2 = new Stone();
		// 将两块石头磨成一把石刀
		StoneKnife sk = StoneKnifeFactory.creatStoneKnife(s1, s2);
		// 砍一块木材
		Wood w = sk.cutTree();
		// 将木材做成椅子
		Chair chair = ChairFactory.creatChair(w);
	}
}


2,  球从一根绳子的一端移动到了另一端

两个对象:    球Ball

每个球都应该有一个绳子来指引移动的方向,有一个起始位置,有一个移动的方法,就是从一点到另一点,调用绳子的方法

public class Rope {

	// 绳子的两个端点,一个代表起点,一个代表终点
	private Point start;
	private Point end;

	public Rope(Point start, Point end) {
		this.start = start;
		this.end = end;
	}

	// 从一个点到另一个点
	public Point nextPoint(Point point) {
		// 应根据传进来的点,返回指定的点
		return new Point();
	}
}

绳子 Rope

为球的移动提供方向,两个属性,起始点和终点,有一个方法,获取下一个点

public class Ball {

	// 为每个球指定一个绳子
	private Rope rope;
	// 每个球都有起始位置
	private Point currentPoint;

	public Ball(Rope rope, Point currentPoint) {
		this.rope = rope;
		this.currentPoint = currentPoint;
	}

	// 球移动的方法,从绳子一端移动到另一端
	public void move() {
		// 移动到了currentPoint点
		currentPoint = rope.nextPoint(currentPoint);
		System.out.println("小球移动到了" + currentPoint);
	}
}

交通灯思路:

已知一共有12条路线,右转4条,左转4条,直行4条

         右转不受交通灯控制,视为常绿

         现在考虑8条路线,因为来往是对称的,所以只用考虑4条路线

分别是

按红,黄,蓝,绿,的顺序

         红:SàN直行,该路上绿灯,其它都是红灯

         黄:直行结束后,黄:SàW左转,该路上左转灯亮绿灯

         蓝:竖着的路行驶结束后,换横着的马路,EàW,

         绿:直行结束,再接着该路上左转,EàS

 

由上可知,4条路线轮流变换红绿灯行驶

 

交通灯:

         使用枚举类,

         总共有12条路线,对应的就有12个灯

         实际上只需要考虑4个灯轮流交换

 

交通灯有3个成员变量

一个boolean类型记录自己的状态,是红灯还是绿灯亮

一个String类型变量记录对应方向灯的状态

一个String类型变量记录下一个灯

 

两个方法,一个是点亮绿灯

                     一个是绿灯变红灯

//总共12个灯,定义枚举,指定12个Lamp元素即可
public enum Lamp {
	
	// 使用String类型变量来封装枚举名,并在初始化中使用,可以避免非法向前引用的问题
	S2N("N2S", false, "S2W"), // 1,竖着的马路,向上直行
	S2W("N2E", false, "E2W"), // 2,竖着的马路,左转弯
	E2W("W2E", false, "E2S"), // 3,横着的马路,直行
	E2S("W2N", false, "S2N"), // 4,横着的马路,左转弯
	/* 右转路线,灯为常绿 */
	S2E(null, true, null), E2N(null, true, null), N2W(null, true, null), W2S(
			null, true, null),
	/* 对应方向的灯,不需要进行逻辑考虑,只需遵守上面4个灯的规则就行 */
	N2S(null, false, null), N2E(null, false, null), W2E(null, false, null), W2N(
			null, false, null);
	// 记录当前状态
	private boolean lighted;
	// 与灯同时为绿的对应方向的灯,保存的是灯的名字,后面可以根据灯的名字获取对应的实例对象
	private String opposite;
	// 灯变红时,下一个变绿的灯
	private String next;

	// 初始化灯,枚举的构造方法必须是私有
	private Lamp(String oppsite, boolean lighted, String next) {
		this.opposite = oppsite;
		this.lighted = lighted;
		this.next = next;
	}

	// 判断当前灯是否是亮的
	public boolean isLighted() {
		return lighted;
	}

	// 当前灯变绿,随之要将对应的灯也变绿
	public void light() {
		this.lighted = true;
		// 调用自己方法,将对应的灯也变绿,通过灯名获取对应灯的实例对象
		if (opposite != null) {
			Lamp opp = Lamp.valueOf(opposite);
			opp.light();
			System.out.println("当前绿的灯是"+name()+"和"+opposite+"还有右转弯一共6个绿灯");
		}
	}

	// 当前灯变红,同时返回下一个变绿的灯
	public Lamp blackOut() {
		this.lighted = false;
		// 将对应方向的灯也变红
		if (opposite != null) {
			Lamp.valueOf(opposite).blackOut();
		}
		// 获得下一个绿灯,并返回
		Lamp nextLamp = null;
		if (next != null) {
			nextLamp = Lamp.valueOf(next);
			// 将下一个灯变绿
			nextLamp.light();
			System.out.println(name()+"和"+opposite+"变红了,"+next+"灯绿了");
		}
		return nextLamp;
	}
}

交通灯的控制器

一个成员变量,用来记录当前的灯

 

一个方法,定义一个计时器,每过10秒,将当前灯变红,并获取下一个变绿的灯

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

//灯的控制器
public class LampController {

	// 当前亮的灯
	private Lamp currentLamp;

	public LampController() {
		// 指定第一个亮的灯
		currentLamp = Lamp.S2N;
		// 将该灯变绿
		currentLamp.light();

		// 定义一个计时器,每隔指定时间就将当前灯变红,并将下一个灯变绿
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		// 按照指定频率执行线程中的方法中的代码
		timer.scheduleAtFixedRate(new Runnable() {
			// run方法中是指定的要执行的代码
			public void run() {
				// 将当前灯变黑,同时将当前灯指向下一个变绿的灯
				currentLamp = currentLamp.blackOut();
			}
		}, 10, 10, TimeUnit.SECONDS);
	}
}


Road类,描述公路

定义一个集合,封装String类型数据,来代表车辆

一共有12条路线,所以每创建一条路线都给该路线指定对应的名字

 

单独封装一个线程来模拟路上来的车辆,即每条路上随机增加的车辆

 

再单独封装一个线程来模拟过马路的车辆,即路上减少的车辆

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 {

	// 定义集合存储车辆
	List<String> vehicles = new ArrayList<String>();
	// 每条路都有自己的名字,根据该名字也可以获得该路上对应的灯
	private String name;

	public Road(String name) {
		this.name = name;

		// 获得线程池中的一个线程,来向路上添加车辆
		ExecutorService pool = Executors.newSingleThreadExecutor();
		// new一个Runnable对象,往里面封装添加车辆的代码
		pool.execute(new Runnable() {
			public void run() {

				for (int i = 1; i <= 1000; i++) {
					// 每隔1——10秒就添加一辆车辆
					try {
						Thread.sleep((new Random().nextInt(10) + 1) * 1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vehicles.add(Road.this.name + "_" + i);
				}
			}
		});

		// 下面定义方法减少车辆,即车辆穿过路口,也是单独封装到 一个线程中去
		// 定义一个线程调度池
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);

		// 按固定频率执行线程中的代码,延迟1s执行,之后过1s再执行该代码
		timer.scheduleAtFixedRate(new Runnable() {
			public void run() {
				// 有车辆才运行
				if (vehicles.size() > 0) {
					// 根据路名获取路灯
					Lamp lamp = Lamp.valueOf(Road.this.name);
					// 如果是绿灯亮
					if (lamp.isLighted()) {
						System.out.println(vehicles.remove(0) + "正在过马路!");
					}
				}
			}
		}, 1, 1, TimeUnit.SECONDS);
	}
}

场景类:

public class MainClass {

	public static void main(String[] args) {

		// 将12条路线都创建出来
		String[] directors = { "S2N", "S2W", "E2W", "E2S", "S2E", "E2N", "N2W",
				"W2S", "N2S", "N2E", "W2E", "W2N" };
		for (String director : directors) {
			new Road(director);
		}
		new LampController();
	}
}

运行结果:

当前绿的灯是S2N和N2S还有右转弯一共6个绿灯
S2N_1正在过马路!
S2E_1正在过马路!
W2S_1正在过马路!
S2N_2正在过马路!
N2W_1正在过马路!
S2E_2正在过马路!
E2N_1正在过马路!
E2N_2正在过马路!
W2S_2正在过马路!
N2S_1正在过马路!
当前绿的灯是S2W和N2E还有右转弯一共6个绿灯
S2N和N2S变红了,S2W灯绿了
S2W_1正在过马路!
N2E_1正在过马路!
S2W_2正在过马路!
N2E_2正在过马路!
S2W_3正在过马路!
E2N_3正在过马路!
S2W_4正在过马路!
N2W_2正在过马路!
E2N_4正在过马路!
N2E_3正在过马路!
W2S_3正在过马路!
S2E_3正在过马路!
当前绿的灯是E2W和W2E还有右转弯一共6个绿灯
S2W和N2E变红了,E2W灯绿了
E2W_1正在过马路!
N2W_3正在过马路!
W2E_1正在过马路!
E2W_2正在过马路!
E2N_5正在过马路!
W2E_2正在过马路!
E2W_3正在过马路!
E2W_4正在过马路!
W2S_4正在过马路!
W2E_3正在过马路!
N2W_4正在过马路!

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

你可能感兴趣的:(线程池,面向对象思想,模拟交通灯管理)