题目不是很清楚,我仔细说来。
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分,给两个人。不明白的地方尽快问我。其他的别扯。
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分,给两个人。不明白的地方尽快问我。其他的别扯。
系统被化简了,但是因为我使用了名字,使得系统的重构变成一个问题了。
如果这个Observer类不知道会有什么样的事件会让自己处理,那自己是没有办法实现对应的方法的啊.因为我现在不做java了,我做.net,会定义一些event或者delegate.但是这个和定义接口其实是一样的.
这个同样需要知道外界会有什么事件需要让自己来处理.不知道我说的你是否明白.其实如果你的需求只是需要设计一个组否flexible的Observer,让她能够很容易的去应变更多的需求,响应更多的事件.
我觉得可以这么做.
在Observer类里面设计一个方法,这个方法作为所有事件的转发中枢.这个方法只负责转发事件,而事件处理设计一个接口,在这个Observer类之外会有很多的实现这个接口的类,他们负责真正的处理事件.这个转发中枢函数对于实现类的调用可以使用反射,这样在Fire事件的时候,只要传进去对应事件的名字就可以.
Register的时候,其实就是创建对应的事件处理实现类.
比如你做.Net,界面元素需要得到回调事件的时候,某个线程会Call这个Callback方法,但是方法中可能涉及到很多UI的元素。
在.Net里面,我们会调用Control.Invoke吧? 实际就是Win32的SendMessage的封装,
尽管我对Swing的了解不多,但是知道它的线程似乎也有类似的问题。所以我们得考虑啊?PS:实际上我做系统的时候,最讨厌这种不关逻辑表达的现场切换了。试想,如果我们有N个对象都是UI的元素,关注这个其他线程Send过来的消息,我们切换一次线程,还是多次呢?
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();
}
}}
按我上面的思路实现的,不知道靠谱不靠谱,各位大侠不要拍我……
if(!observerMap.containsKey(eventName))
throw new NoSuchEventException();
我的原意是所有可能出现的事件都以 String 的形式作为常量保存在 Manager 中,然后当调用事件方法时,如果常量里不存在这个事件,就应该抛出这个异常,刚刚没细想,写成这样了……
我觉得我们学的设计模式中讲到的Obsever绝对能满足你的要求了吧甘草...我强烈要求你加我MSN,你都不加我....
老师讲的挺好的嘛.....
应该都知道吧...去年做了个类似LOG4J的一个LOG的library的时候我自己也有加如这个模式....
甘草说的太玄乎了点吧...
其实很简单吧...我们有几个设备是被观察的,另外几个设备是用来监测上述设备的变化的(相当于显示器),一旦被观察的设备发生变化我们就能动态地去告诉那些显示器嘛.....最多再多一个人动态加入和删除功能啊.....
呵呵,貌似书上都有说的哦
^_^
所以呢,强烈推荐headfirst(不知道谁翻译的中文名字好淫荡...深入浅出....)
第一个问题
先说明这个思路很好 可以避免耦合
解决办法:看来只能用反射的办法了
先注册
后循环取出 然后反射其方法 如果有fire的方法就调用之目前反射的性能已经足够好 性能不是问题
我的意思是:关于线程问题我想 不应该在调用方法上
应该在Obsever 的fire方法中处理
而这个方法 是与你的业务逻辑相关的
不应与这个观察者模式耦合在一起
这才是一个框架。
线程? 反射?事件触发,回调 关注事态发展