【再考大家一个题目】设计一个Observer回调系统

healer_kx 2008-03-20 04:39:56
题目不是很清楚,我仔细说来。
1. 要求任意一个Object都可以成为Observer。但是你不可以使用统一的接口。【这种我们称为非侵入式,有统一接口的称为侵入式】
2. 要求考虑线程问题。比如我们的Observer是一个SWT的对象,或者是一个Swing的对象,但是时间的fire者在其他的Work Thread。要求处理线程切换。
3.


大致的样子应该满足这样的代码规范。

class MyObserver {
void onEventMessage(...) {}
}


你可能需要注册他。
那么我们大致可能会写成这个样子。
register(new MyObserver());


然后在某一个线程,我们可能回调事件给这个Observer。当然了。有很多个Observer,可是它们并非派生自同一个接口哦。
fire(o, /*some event*/);
大概是这个样子。


如果我们希望MyObserver 对象还关注其他的事件,只要在里面加个方法就可以了。当然了,你可以考虑命名耦合,这没有关系。


这次不考算法了,上次居然看到了C语言的答案。
大多数的Java程序员第一个想到的肯定是公共的接口,但是这个很简单,而实际中的系统可能有许多事件,你很难划分事件的接口从属。
以QQ为例,用户上线的回调事件接口方法,和用户消息到来的回调事件接口方法,是应该放到一个接口声明中嘛?
你想想? 使劲想,想不通的时候,你们就知道接口编程的经典也是一种痛苦了。会让你在设计阶段就耗费很多时间和精力。




好了,200分,给两个人。不明白的地方尽快问我。其他的别扯。
...全文
398 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
wren4255 2008-03-25
  • 打赏
  • 举报
回复
ぜんぜん分からないけれども。。。。。。
lpingxh 2008-03-23
  • 打赏
  • 举报
回复
比较高深的问题,有关线程切换,前两天用SWT的时候就碰到类似的问题,学习中。。。
healer_kx 2008-03-22
  • 打赏
  • 举报
回复
UP
qxwandy1 2008-03-22
  • 打赏
  • 举报
回复
好像比较有技术含量
xlongbuilder 2008-03-21
  • 打赏
  • 举报
回复
反射和线程关系不大 是对的
我的意思是:

关于线程问题我想 不应该在调用方法上
应该在Obsever 的fire方法中处理
而这个方法 是与你的业务逻辑相关的
不应与这个观察者模式耦合在一起
healer_kx 2008-03-21
  • 打赏
  • 举报
回复
to xlong, good

反射和线程关系不大,但是这个是一个系统,系统说粗俗了,就是把各种东西放进去,还不能乱。
xlongbuilder 2008-03-21
  • 打赏
  • 举报
回复
线程的问题粗看起来
貌似 若用反射不需要处理线程问题吧
xlongbuilder 2008-03-21
  • 打赏
  • 举报
回复

第一个问题
先说明这个思路很好 可以避免耦合
解决办法:

看来只能用反射的办法了
先注册
后循环取出 然后反射其方法 如果有fire的方法就调用之

目前反射的性能已经足够好 性能不是问题

ttlyfast 2008-03-21
  • 打赏
  • 举报
回复
啥是 Observer ?
dracularking 2008-03-21
  • 打赏
  • 举报
回复
大致看了下 不知道甘草说的和传统的Observer有什么区别
线程? 反射?事件触发,回调 关注事态发展
yuwenbao 2008-03-21
  • 打赏
  • 举报
回复
先占个位,做个标记,慢慢想
cchaha 2008-03-21
  • 打赏
  • 举报
回复
alert("mark")
healer_kx 2008-03-21
  • 打赏
  • 举报
回复
两个东西放在一起就是耦合嘛?或许你可以用两个系统完成这个事情。但是我把它们放在一起后,你感觉不到Thread的switch了。
这才是一个框架。
healer_kx 2008-03-20
  • 打赏
  • 举报
回复
MSN就是我的注册邮箱,163的。

我只研究那些不实际的问题,加了也没用。
nihuajie05 2008-03-20
  • 打赏
  • 举报
回复
你说的是不是设计模式里的那个Obsever啊???
我觉得我们学的设计模式中讲到的Obsever绝对能满足你的要求了吧

甘草...我强烈要求你加我MSN,你都不加我....
zjhlht 2008-03-20
  • 打赏
  • 举报
回复
甘草的帖~~~~

先收藏了再说~~~~以我现在水平还解决不了~~~

ninesea 2008-03-20
  • 打赏
  • 举报
回复
一直不明白回调是什么意思 到是看到过很多次 借这个贴子问一下 谁给指个方向 看什么书可以明白这个概念
哈哈 打扰甘草一下
Caesary 2008-03-20
  • 打赏
  • 举报
回复
上面这一行应该改一下
if(!observerMap.containsKey(eventName))
throw new NoSuchEventException();
我的原意是所有可能出现的事件都以 String 的形式作为常量保存在 Manager 中,然后当调用事件方法时,如果常量里不存在这个事件,就应该抛出这个异常,刚刚没细想,写成这样了……
Caesary 2008-03-20
  • 打赏
  • 举报
回复
Observer 包装类:

public class ObserverPack {

private Object obj = null;

private Method onEventMethod = null;

public ObserverPack(Object obj, String onEventMethod)
throws SecurityException, NoSuchMethodException{
this.obj = obj;
this.onEventMethod = obj.getClass().getMethod(onEventMethod);
}

public void onEvent()
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException{
onEventMethod.invoke(obj);

}

}


事件及 Observer 管理类:

public class Manager {

public static final String AEVENT = "AEVENT";

private Map<String, List<ObserverPack>> observerMap =
new HashMap<String, List<ObserverPack>>();

public void addObserver(Object object, String method, String eventName)
throws SecurityException, NoSuchMethodException{
if(observerMap.containsKey(eventName))
observerMap.get(eventName).add(new ObserverPack(object, method));
else{
List<ObserverPack> observers = new ArrayList<ObserverPack>();
observers.add(new ObserverPack(object, method));
observerMap.put(eventName, observers);
}
}

public void onEvent(String eventName)
throws Exception{

if(!observerMap.containsKey(eventName))
throw new NoSuchEventException();

for(ObserverPack op : observerMap.get(eventName))
op.onEvent();

}

}


原始 Observer 类:

public class PrimalObserver {

public void onEvent(){

System.out.println("On Event!");

}

}


不存在事件异常:

@SuppressWarnings("serial")
public class NoSuchEventException extends Exception {

}


测试类:

public class ObserverTest {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Manager manager = new Manager();

PrimalObserver po = new PrimalObserver();

try {
manager.addObserver(po, "onEvent", Manager.AEVENT);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

try {
manager.onEvent(Manager.AEVENT);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}


按我上面的思路实现的,不知道靠谱不靠谱,各位大侠不要拍我……
healer_kx 2008-03-20
  • 打赏
  • 举报
回复
线程的问题由来:
比如你做.Net,界面元素需要得到回调事件的时候,某个线程会Call这个Callback方法,但是方法中可能涉及到很多UI的元素。
在.Net里面,我们会调用Control.Invoke吧? 实际就是Win32的SendMessage的封装,
尽管我对Swing的了解不多,但是知道它的线程似乎也有类似的问题。所以我们得考虑啊?

PS:实际上我做系统的时候,最讨厌这种不关逻辑表达的现场切换了。

试想,如果我们有N个对象都是UI的元素,关注这个其他线程Send过来的消息,我们切换一次线程,还是多次呢?
加载更多回复(10)

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧