java:Observable/Observer模式在SWT环境下UI线程/非UI线程的透明化调用

24 篇文章 0 订阅

观察者模式(Observable/Observer)在UI设计方面非常有用,可以通过Observer来实现UI界面的更新,因而可以实现UI层与业务层的分离。
但是我们知道大部分UI框架(比如SWT)都要区分UI线程和非UI线程,如果Observable对象在非UI线程执行notifyObservers操作,而Observer的update方法又涉及UI对象的操作时就会抛出异常。(参见 《SWT的UI线程和非UI线程》)

如果Observer的代码不用关心自己是不是在UI线程,就可以降低Observer代码的复杂度,所以为解决这个问题,我对Observable做了进一步封装。
SWTObservable.java

package net.gdface.ui;

import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import org.eclipse.swt.widgets.Display;

/**
 * SWT环境下对{@link Observable}的易用性封装<br>
 * 实现{@link Observer}类型的侦听器在SWT下UI线程/非UI线程的透明化调用
 * @author guyadong
 *
 */
public class SWTObservable extends Observable {
	/**
	 * {@link Observer}在SWT环境下的重新封装<br>
	 * 实现UI/非UI线程透明化
	 * @author guyadong
	 *
	 */
	class SWTObserver implements Observer {
		final Observer observer;
		/**
		 * 私有构造方法
		 * @param observer
		 */
		private SWTObserver(Observer observer) {
			super();
			if (null == observer)
				throw new IllegalArgumentException("the argument observer must not be null");		
			this.observer = observer;
		}
		@Override
		public void update(Observable o, Object arg) {
			// 判断UI/非UI线程,区别对待
			if (display.getThread() == Thread.currentThread()) {
				observer.update(o, arg);
			} else {
				// 非UI线程下调用 Display.syncExec方法执行
				display.syncExec(new Runnable() {
					@Override
					public void run() {
						observer.update(o, arg);
					}
				});
			}
		}
	}
	/**
	 * 保存所有被 {@link Observable#addObserver(Observer)}方法添加的 {@link SWTObserver}对象,<br>
	 * 以便在 {@link Observable#deleteObserver(Observer)}删除{@link Observer}对象时查找到对应的{@link SWTObserver}对象
	 */
	private final Vector<SWTObserver> listeners=new Vector<SWTObserver>();
	private final Display display;
	SWTObservable(Display display) {
		if (null == display)
			throw new IllegalArgumentException("the argument display must not be null");		
		this.display = display;
	}
	/**
	 * 在 {@link #listeners}中 查找{@link Observer}对应的{@link SWTObserver}对象,找不到则返回null
	 * @param listener
	 * @return
	 */
	private SWTObserver find(Observer listener){
		for(SWTObserver o:this.listeners){
			if(o.observer==listener)return o;
		}
		return null;
	}
	@Override
	public synchronized void addObserver(Observer o) {
        add(o);	
	}

	@Override
	public synchronized void deleteObserver(Observer o) {
		delete(o);
	}
	synchronized SWTObserver add(Observer o) {
        if (null==find(o)) {
        	SWTObserver obs = new SWTObserver(o);
        	this.listeners.add(obs);
            super.addObserver(obs);
            return obs;
        }		
        return null;
	}
	synchronized SWTObserver delete(Observer o) {
		SWTObserver obs = find(o);
		if(null!=obs){
			this.listeners.remove(obs);
			super.deleteObserver(obs);
		}
		return obs; 
	}
	@Override
	public void notifyObservers(Object arg) {
		setChanged();
		super.notifyObservers(arg);
	}
}


参考资料:
《设计模式之观察者模式(Observable与Observer)》http://www.cnblogs.com/xudong-bupt/p/3428108.html
《SWT的UI线程和非UI线程》http://blog.csdn.net/dollyn/article/details/38582743

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值