java设计模式之——观察者模式observer (附带读取配置文件)

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

题目:小孩子睡醒后,监护者做出一些列反映。比如:爸爸喂奶、爷爷抱抱、狗狗叫几声。

设计思路:

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、运行结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值