Oberserver模式的变种AsyncToken
在周末的设计过程中,需要用到Observer模式,但当时纠结了一下是否真的需要使用Observer模式,在Google了一下以后,找到了[设计模式]AsyncToken模式,替换通常的Listener模式这篇文章。先贴一下样例代码吧,完整的代码可以参考这个连接
package cn.org.rapid_framework.util.concurrent.async; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.swing.SwingUtilities; /** * <pre> * public void testSendEmail() { * final String address = "badqiu(a)gmail.com"; * final String subject = "test"; * final String content = "async token test"; * AsyncToken token = sendAsyncEmail(address,subject,content); * * token.addResponder(new IResponder() { * public void onFault(Exception fault) { * System.out.println("email send fail,cause:"+fault); * sendAsyncEmail(address,subject,content); * } * public void onResult(Object result) { * System.out.println("email send success,result:"+result); * } * }); * } * * public AsyncToken sendAsyncEmail(String address,String subject,String content) { * final AsyncToken token = new AsyncToken(); * * Thread thread = new Thread(new Runnable() { * public void run() { * try { * //do send email job... * token.setComplete(executeResult); * }catch(Exception e) { * token.setFault(e); * } * } * }); * thread.start(); * * return token; * } * </pre> * @see AsyncTokenTemplate * @author badqiu */ public class AsyncToken<T> { public static final String DEFAULT_TOKEN_GROUP = "default"; private static AtomicLong tokenIdSequence = new AtomicLong(1); //tokenGroup tokenName tokenId private String tokenGroup = DEFAULT_TOKEN_GROUP; private String tokenName; private long tokenId; private List<IResponder> _responders = new ArrayList(2); private UncaughtExceptionHandler uncaughtExceptionHandler; private T _result; private Exception _fault; private boolean _isFiredResult; private CountDownLatch awaitResultSignal = null; public AsyncToken(){ this(null); } public AsyncToken(UncaughtExceptionHandler uncaughtExceptionHandler) { this(DEFAULT_TOKEN_GROUP,null); this.uncaughtExceptionHandler = uncaughtExceptionHandler; } public AsyncToken(String tokenGroup,String tokenName) { setTokenGroup(tokenGroup); setTokenName(tokenName); this.tokenId = tokenIdSequence.getAndIncrement(); } public String getTokenGroup() { return tokenGroup; } public void setTokenGroup(String tokenGroup) { if(tokenGroup == null) throw new IllegalArgumentException("'tokenGroup' must be not null"); this.tokenGroup = tokenGroup; } public String getTokenName() { return tokenName; } public void setTokenName(String tokenName) { this.tokenName = tokenName; } public long getTokenId() { return tokenId; } /** * addResponder(responder,false); * @param responder */ public void addResponder(final IResponder<T> responder) { addResponder(responder,false); } /** */ public void addResponder(final IResponder<T> responder,boolean invokeResponderInOtherThread) { _responders.add(responder); if(_isFiredResult) { if(invokeResponderInOtherThread) { SwingUtilities.invokeLater(new Runnable() { public void run() { fireResult2Responder(responder); } }); }else { fireResult2Responder(responder); } } } public List<IResponder> getResponders() { return _responders; } public boolean hasResponder() { return _responders != null && _responders.size() > 0; } public UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler; } public void setUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler) { this.uncaughtExceptionHandler = uncaughtExceptionHandler; } private void fireResult2Responder(IResponder responder) { try { if(_fault != null) { responder.onFault(_fault); }else { responder.onResult(_result); } }catch(RuntimeException e) { if(getUncaughtExceptionHandler() != null) { getUncaughtExceptionHandler().uncaughtException(responder, e); }else { throw e; } }catch(Error e) { if(getUncaughtExceptionHandler() != null) { getUncaughtExceptionHandler().uncaughtException(responder, e); }else { throw e; } } } private void fireResult2Responders() { synchronized (this) { _isFiredResult = true; if(awaitResultSignal != null) { awaitResultSignal.countDown(); } } for(IResponder r : _responders) { fireResult2Responder(r); } } public void setComplete(){ setComplete(null); } public void setComplete(T result) { if(_isFiredResult) throw new IllegalStateException("token already fired"); this._result = result; fireResult2Responders(); } public void setFault(Exception fault) { if(fault == null) throw new NullPointerException(); if(_isFiredResult) throw new IllegalStateException("token already fired"); this._fault = fault; fireResult2Responders(); } public boolean isDone() { synchronized (this) { return _isFiredResult; } } /** * @see Future */ public Object waitForResult() throws InterruptedException,Exception { return waitForResult(-1, null); } /** * @see Future */ public Object waitForResult(long timeout,TimeUnit timeUnit) throws InterruptedException,Exception { synchronized(this) { if(_isFiredResult) { if(_fault != null) { throw _fault; }else { return _result; } } awaitResultSignal = new CountDownLatch(1); } if(timeout > 0) { awaitResultSignal.await(timeout,timeUnit); }else { awaitResultSignal.await(); } if(_fault != null) { throw _fault; }else { return _result; } } }
文章总结了AsyncTokenVS Observer好处和异同
使用AsyncToken的好处:
1. token可以无限传递,只要对方法的执行结果感兴趣,都可以监听方法的执行结果.
2. 拥有上下文,还可以引用前面的参数,以执行任务email重发这种任务
3. 一个token与一个方法对应,方法调用时你即知道token对应的事件,不需要使用listener模式中的一般用EventType来区别不现的事件
3. 灵活转换,也可以将上面的token再转至listener,再由listener以事件的方式派发事件
与Listener的异同:
1.token可以无限传递
2.没有使用事件或是监听不同的方法,listener一般配合需要使用事件,然后由事件进行参数的绑定.
3.listener模式一般是先设置好listener,而AsyncToken可以得到token后再添加监听方法

蝴蝶结贵族服饰,2010年我们做的会更好!
蝴蝶结贵族服饰.http://shop60655251.taobao.com/