本案例设计到设计模式中的观察者模式(订阅发布)
一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,与的是看电视(有点不合理)
B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家。
如此就形成了一个需求,放哨的学生要通知所有玩的学生:老师来了,而不同的学生有不同的反应,有的马上把电视关闭,有的停止玩游戏。
设计的要求如下,让A类学生和B类学生完全解耦,即A类完全不知道B类的学生,却可以通知B类的学生。
代码及说明如下:
Event 类,定义了一个事件类:
-
package
lnurd.test;
-
-
import
java.lang.reflect.Method;
-
import
java.util.Date;
-
-
public
class
Event {
-
//要执行方法的对象
-
private
Object object;
-
//要执行的方法名称
-
private
String methodName;
-
//要执行方法的参数
-
private
Object[] params;
-
//要执行方法的参数类型
-
private
Class[] paramTypes;
-
-
public
Event(){
-
-
}
-
public
Event(Object object,String methodName,Object…args){
-
this
.object=object;
-
this
.methodName=methodName;
-
this
.params=args;
-
contractParamTypes(
this
.params);
-
}
-
//根据参数数组生成参数类型数组
-
private
void
contractParamTypes(Object[] params){
-
this
.paramTypes=
new
Class[params.length];
-
for
(
int
i=
0
;i<params.length;i++){
-
this
.paramTypes[i]=params[i].getClass();
-
}
-
}
-
-
public
Object getObject() {
-
return
object;
-
}
-
//若干setter getter省略
-
public
void
setParamTypes(Class[] paramTypes) {
-
this
.paramTypes = paramTypes;
-
}
-
//执行该 对象的该方法
-
public
void
invoke()
throws
Exception{
-
Method method=object.getClass().getMethod(
this
.getMethodName(),
this
.getParamTypes());
-
if
(
null
==method){
-
return
;
-
}
-
method.invoke(
this
.getObject(),
this
.getParams());
-
}
-
}
EventHandler类,若干Event类的载体,同时提供一个执行所有Event的方法
-
package
lnurd.test;
-
-
import
java.util.ArrayList;
-
import
java.util.List;
-
-
public
class
EventHandler {
-
//是用一个List
-
private
List<Event> objects;
-
-
public
EventHandler(){
-
objects=
new
ArrayList<Event>();
-
}
-
//添加某个对象要执行的事件,及需要的参数
-
public
void
addEvent(Object object,String methodName,Object…args){
-
objects.add(
new
Event(object,methodName,args));
-
}
-
//通知所有的对象执行指定的事件
-
public
void
notifyX()
throws
Exception{
-
for
(Event e : objects){
-
e.invoke();
-
}
-
}
-
}
放哨的学生:这里先抽象出一个抽象类,因为放哨的人有尽职尽责的,也有马马虎虎的,
但是他们有功能的方法1。增加需要帮忙放哨的学生 2。通知所有需要放哨的学生:老师来了
-
package
lnurd.test;
-
-
public
abstract
class
Notifier {
-
private
EventHandler eventHandler=
new
EventHandler();
-
-
public
EventHandler getEventHandler() {
-
return
eventHandler;
-
}
-
public
void
setEventHandler(EventHandler eventHandler) {
-
this
.eventHandler = eventHandler;
-
}
-
//增加需要帮忙放哨的学生
-
public
abstract
void
addListener(Object object,String methodName,Object…args);
-
//告诉所有要帮忙放哨的学生:老师来了
-
public
abstract
void
notifyX();
-
}
接着是放哨人的具体实现了,这里仅实现两个
1尽职尽责的放哨人GoodNotifier
2马马虎虎的放哨人BadNotifier
-
package
lnurd.test;
-
-
public
class
GoodNotifier
extends
Notifier {
-
-
@Override
-
public
void
addListener(Object object, String methodName, Object… args) {
-
System.out.println(
“有新的同学委托尽职尽责的放哨人!”
);
-
this
.getEventHandler().addEvent(object, methodName, args);
-
}
-
-
@Override
-
public
void
notifyX() {
-
System.out.println(
“尽职尽责的放哨人告诉所有需要帮忙的同学:老师来了”
);
-
try
{
-
this
.getEventHandler().notifyX();
-
}
catch
(Exception e){
-
e.printStackTrace();
-
}
-
}
-
-
}
-
-
//对于BadNotifier代码类似,不再复述.
接下来是玩游戏的学生:PlayingGameListener
-
package
lnurd.test;
-
-
import
java.util.Date;
-
-
public
class
PlayingGameListener {
-
public
PlayingGameListener(){
-
System.out.println(
“我正在玩游戏 开始时间”
+
new
Date());
-
}
-
public
void
stopPlayingGame(Date date){
-
System.out.println(
“老师来了,快回到座位上,结束时间”
+date);
-
}
-
}
在接下来是看电视的学生WatchingTVListener
-
package
lnurd.test;
-
-
import
java.util.Date;
-
-
public
class
WatchingTVListener {
-
public
WatchingTVListener(){
-
System.out.println(
“我正在看电视 ”
+
new
Date());
-
}
-
public
void
stopWatchingTV(Date date){
-
System.out.println(
“老师来了,快关闭电视 。 结束时间”
+date);
-
}
-
}
测试代码:
-
//创建一个尽职尽责的放哨者
-
Notifier goodNotifier=
new
GoodNotifier();
-
-
//创建一个玩游戏的同学,开始玩游戏
-
PlayingGameListener playingGameListener=
new
PlayingGameListener();
-
//创建一个看电视的同学,开始看电视
-
WatchingTVListener watchingTVListener=
new
WatchingTVListener();
-
//玩游戏的同学告诉放哨的同学,老师来了告诉一下
-
goodNotifier.addListener(playingGameListener,
“stopPlayingGame”
,
new
Date());
-
//看电视的同学告诉放哨的同学,老师来了告诉一下
-
goodNotifier.addListener(watchingTVListener,
“stopWatchingTV”
,
new
Date());
-
try
{
-
//一点时间后
-
Thread.sleep(
1000
);
-
}
catch
(Exception e){
-
e.printStackTrace();
-
}
-
//老师出现,放哨的人通知所有要帮忙的同学:老师来了
-
goodNotifier.notifyX();
- 笔者总结:事件委托的本质是,我们把所有操作都当做是调用某一个实例的某一个方法(有时需要参数),那么通过java的反射,穿入实例和方法名就可以做统一的处理。
版权声明:本文为pj10405135原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。