前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java:Observable/Observer模式在SWT环境下UI线程/非UI线程的透明化调用

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

作者头像
10km
发布2019-05-25 22:28:00
4770
发布2019-05-25 22:28:00
举报
文章被收录于专栏:10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433696

观察者模式(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

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年12月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档