您的位置:首页 > 其它

用观察者模式设计一个交通信号灯调度系统

2014-04-20 19:12 344 查看
	这是本人在CSDN上的第一篇博客,写一篇有关于Java中设计模式,多线程调度的一个Demo吧,本人水平有限,望各位博友批评指正。此Demo实现了现实交通信号灯调度车辆通行的功能,为了方便大家理解,省去了黄色信号灯。
最近看了一些Java中的设计模式,比如最简单的单例模式,抽象工厂模式,观察者模式等。在学习了这些设计模式之后,我又对之前写过的一些程序做了改进,本文贴一个交通信号灯的系统,废话不多说,先看一种没有用观察者模式的实现(这种实现来源于传智播客的张孝祥老师的Java多线程课程中的一道面试题,有兴趣的博友可以查看点击打开链接)。
在附代码前先看一下需求吧:

Ø 异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
Ø 信号灯忽略黄灯,只考虑红灯和绿灯。
Ø 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
Ø 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
Ø 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
Ø 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
源代码:
Lamp.java

public enum Lamp {

S2N("N2S", "S2W", false), S2W("N2E", "E2W", false), E2W("W2E", "E2S", false), E2S(
"W2N", "S2N", false), 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 Lamp(String opposite, String next, boolean lighted) {
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}

private String opposite;
private String next;
private boolean lighted;

public boolean isLighted() {
return lighted;
}

public void light() {
this.lighted = true;
if (opposite != null) {
Lamp.valueOf(opposite).light();
}
System.out.println(name() + "方向的灯变绿了,下面将有6个方向的车辆通过!");
}

public Lamp blackOut() {
/* 下面将当前路的灯变红 */
this.lighted = false;
if (opposite != null) {
Lamp.valueOf(opposite).blackOut();
}
/* 下面将下面一条路的灯变绿 */
Lamp nextLamp = null;
if (next != null) {
nextLamp = Lamp.valueOf(next);
System.out.println(next + "方向的灯由红变绿了!");
nextLamp.light();
}
return nextLamp;
}
}


LampController.java

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

public class LampController {
private Lamp currentLamp;

public LampController(Lamp lamp) {
currentLamp = lamp;
currentLamp.light();
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
currentLamp = currentLamp.blackOut();
}
}, 10, 10, TimeUnit.SECONDS);
}
}


Road.java

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Road {
private String name;// 路名
private List<String> vehicles = new ArrayList<String>();//车辆集合

public Road(String name) {
this.name = name;
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.schedule(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
try {
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
vehicles.add("" + i);
}
}
}, 0, TimeUnit.SECONDS);
ScheduledExecutorService timer2 = Executors.newScheduledThreadPool(1);
timer2.scheduleAtFixedRate(new Runnable() {

@Override
public void run() {
if (vehicles.size() > 0) {
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
if (lighted) {
String current = vehicles.remove(0);
System.out.println(Road.this.name + "路的当前第" + current
+ "号正在通过路口!");
}
}
}
}, 1, 1, TimeUnit.SECONDS);
}
}


Main.java

public class Main {
public static void main(String[] args) {
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(Lamp.S2N);
}
}


下面是使用观察者模式的方法:

Lamp.java

import java.util.Observable;

public class Lamp extends Observable {
public Lamp(boolean lighted, String name) {
this.lighted = lighted;
this.name = name;
}

private Lamp opposite;
private Lamp next;
private boolean lighted;
private String name;

public String getName() {
return name;
}

public void setNext(Lamp next) {
this.next = next;
}

public void setOpposite(Lamp opposite) {
this.opposite = opposite;
}

public boolean isLighted() {
return lighted;
}

public void light() {
this.lighted = true;
System.out.println(this.name + "方向的灯变绿了!");
if (opposite != null) {
opposite.light();
}
// System.out.println(name+"方向的灯正在发送通知.....");
// 下面两行通知观察者,此方向的路灯已变绿
setChanged();
notifyObservers(Boolean.TRUE);
}

public Lamp blackOut() {
/* 下面将当前路的灯变红 */
this.lighted = false;
System.out.println(name + "方向的灯将要变红了!");
if (opposite != null) {
opposite.blackOut();
}
// 下面两行通知观察者,此方向的路灯已变红
setChanged();
notifyObservers(Boolean.FALSE);

/* 下面将下面一条路的灯变绿 */
Lamp nextLamp = null;
if (next != null) {
nextLamp = next;
nextLamp.light();
}
return nextLamp;
}
}


LampController.java

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

public class LampController {
private Lamp currentLamp;

public LampController() {
Lamp S2N = new Lamp(false, "S2N");
Lamp S2W = new Lamp(false, "S2W");
Lamp E2W = new Lamp(false, "E2W");
Lamp E2S = new Lamp(false, "E2S");
Lamp N2S = new Lamp(false, "N2S");
Lamp N2E = new Lamp(false, "N2E");
Lamp W2E = new Lamp(false, "W2E");
Lamp W2N = new Lamp(false, "W2N");
Lamp S2E = new Lamp(true, "S2E");
Lamp E2N = new Lamp(true, "E2N");
Lamp N2W = new Lamp(true, "N2W");
Lamp W2S = new Lamp(true, "W2S");
S2N.setNext(S2W);
S2W.setNext(E2W);
E2W.setNext(E2S);
E2S.setNext(S2N);

S2N.setOpposite(N2S);
S2W.setOpposite(N2E);
E2W.setOpposite(W2E);
E2S.setOpposite(W2N);
Lamp[] lamps = new Lamp[] { S2N, S2W, E2W, E2S, N2S, N2E, W2E, W2N,
S2E, E2N, N2W, W2S };
for (int i = 0; i < lamps.length; i++) {
new Road(lamps[i]);
if (lamps[i].isLighted()) {
lamps[i].light();
}
}
currentLamp = S2N;
currentLamp.light();
}

public void start() {
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
currentLamp = currentLamp.blackOut();
}
}, 10, 10, TimeUnit.SECONDS);
}
}


Road.java
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
import java.util.Queue;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Road implements Observer {
private String name;// 路名
private Queue<String> vehicles = new LinkedList<String>();// 车辆集合
private Timer timer2 = null;

public Road(Lamp lamp) {
lamp.addObserver(this);// 注册一个观察者
this.name = lamp.getName();
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.schedule(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
try {
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
vehicles.offer("" + i);
}
}
}, 0, TimeUnit.SECONDS);
}

@Override
public void update(Observable o, Object arg) {
if (arg == Boolean.TRUE) {// 绿灯亮了
System.out.println(name + "方向已经开始放行车辆通过!");
timer2 = new Timer();
timer2.schedule(new TimerTask() {
@Override
public void run() {
if (vehicles.size() > 0) {
String current = vehicles.poll();
System.out.println(Road.this.name + "路的当前第" + current
+ "号正在通过路口!");
}
}
}, 1000, 1000);
} else {// 红灯亮了
timer2.cancel();
System.out.println(name + "方向已停止车辆通行!");
}
}
}


Main.java
public class Main {

public static void main(String[] args) {
new LampController().start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: