题目:小孩子睡醒后,监护者做出一些列反映。比如:爸爸喂奶、爷爷抱抱、狗狗叫几声。
设计思路:
1、小孩睡醒后,可以主动呼唤监护者。这里需要用一个线程监控小孩的睡醒状态。
2、每个监护者,针对小孩睡醒后的反映不同。这里可以统一实现方法,具体细节各自不同。
3、为了扩展性,监护小孩者,可以是一位或多位。新增监护者时,尽可能少的修改代码。
4、每次小孩睡醒后,叫监护人时,要把自己的一些参数传给监护者,比如:睡醒时间、睡醒的位置等。
5、尝试采用读取配置文件,动态增减监护人。
注:为了方便起见,所有类写到一个文件内。本例所有的代码均在包 package com.observer.xp5;下面的MyTest.java文件中
1、创建事件类
//创建纪录事件的类
abstract class Event{
}
class WakeUpEvent extends Event{
public long time;//记录事件发生的时间
public String location;//记录事件发生的位置
public Object object;//事件发生时,对应执行人/对象
public WakeUpEvent(long time, String location, Object object) {
super();
this.time = time;
this.location = location;
this.object = object;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
2、创建监护者类
//统一监护者的方法
interface doActionListener{
void doActionWhenWakeUp(WakeUpEvent event);
}
//爸爸的反应
class Baba implements doActionListener{
@Override
public void doActionWhenWakeUp(WakeUpEvent event) {
System.out.println("爸爸喂奶");
}
}
//爷爷的反应
class Yeye implements doActionListener{
@Override
public void doActionWhenWakeUp(WakeUpEvent event) {
System.out.println("爷爷抱一抱");
}
}
//狗子的反应
class Dog implements doActionListener{
@Override
public void doActionWhenWakeUp(WakeUpEvent event) {
System.out.println("狗狗汪汪汪");
}
}
3、创建Baby类,实现Runnable接口,便于启用线程。来监控孩子的睡醒状态
//孩子睡觉,睡醒后主动呼叫监护者
class Baby implements Runnable{
public List<doActionListener> listListeners=new ArrayList<doActionListener>();//存放孩子的监护者
public void addListener(doActionListener listener) {
listListeners.add(listener);//提供给孩子添加监护者的方法
}
@Override
public void run() {
try {
Thread.sleep(5000);//自定义,熟睡5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
wakeUp();//5秒后,睡醒
}
//主动呼叫监护者
void wakeUp() {
System.out.println("baby is wakeing up");
//循环呼叫
for (doActionListener Listener : listListeners) {
Listener.doActionWhenWakeUp(new WakeUpEvent(System.currentTimeMillis(), "bed", Listener));
}
}
}
4、创建配置文件读取类。(核心代码就那么两行)
class PropertyMgr{
private static Properties properties = new Properties();
//只在系统启动的时候加载一次(弊端:配置文件修改后,需要刷新缓存)
static {
try {
//String filePath="observer.properties";//如果配置文件放在根目录,用该写法
String filePath="com/observer/xp5/observer.properties";//读取指定路径包下面的配置文件,比如:和当前class类同级目录
InputStream in=MyTest.class.getClassLoader().getResourceAsStream(filePath);
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String gerProperty(String key) {
return properties.getProperty(key);//根据配置文件中的key获取values
}
}
5、创建配置文件,名称为:“observer.properties”,位置放到项目根目录或者和测试类class同级目录都可以。

#需要被添加到观察者列表的类#
observer=com.observer.xp5.Baba,com.observer.xp5.Yeye,com.observer.xp5.Dog
6、创建测试类分别测试。其中:test1不读取配置文件,test2读取配置文件。
public class MyTest {
//不读取配置文件,代码中的监护者固定
public void test1() {
Baby baby = new Baby();
//添加监护者,一个或多个
baby.addListener(new Baba());
baby.addListener(new Yeye());
baby.addListener(new Dog());
//启动baby的run方法
new Thread(baby).start();
}
//读取配置文件,监护者可以通过配置文件动态配置
public void test2() {
Baby baby = new Baby();
String[] classNames=PropertyMgr.gerProperty("observer").split(",");
for (String className : classNames) {
try {
baby.addListener((doActionListener)Class.forName(className).newInstance());//根据类名反射后,生成新的对象
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//启动baby的run方法
new Thread(baby).start();
}
public static void main(String[] args) {
MyTest test=new MyTest();
//test.test1();//把需要配置的观察者,直接写到程序中,每次变更都需要修改程序
test.test2();//把需要配置的观察者,直接写到配置文件中,每次只需要变更配置文件就可以
}
}
7、运行结果如下:

本文介绍了一个基于观察者模式的应用案例,通过模拟孩子睡醒后触发的一系列动作,展示了如何使用观察者模式进行灵活的事件通知处理。实现了动态添加监听者,并通过配置文件的方式增强了系统的可扩展性。
610

被折叠的 条评论
为什么被折叠?



