zoukankan      html  css  js  c++  java
  • jface databinding:部分实现POJO对象的监测

    在前一篇博文《jface databinding/PojoBindable实现对POJO对象的支持  》中,已经知道直接对POJO对象进行修改,是不能被绑定的UI组件知道的,在上一篇文章中虽然说到PojoBindable这个项目可以解决这个问题,但这个项目并不成熟,所以我没有采用这个方案,而且如果要改造所有的POJO类支持PropertyChangeSupport又实在太麻烦了。  仔细想想我的需求,退而求其次,不一定要直接修改POJO对象,就能实现数据同步可以不?  冷静回头再看相关的资料并做了一些试验,发现原来IObservableValue对象本身就有setValue方法用于修改被监控的对象的值,而且会通知到观察对象。

            DataBindingContext bindingContext = new DataBindingContext();
            // Text对象的text属性的IObservableValue 对象
            IObservableValue observeTextMyNametextObserveWidget = WidgetProperties.text(SWT.Modify).observe(myNametext);
            // Person对象name属性的IObservableValue 对象(Person是个实现了属性get/set方法的POJO类)
            namePersonObserveValue = http://blog.csdn.net/10km/article/details/PojoProperties.value("name").observe(person);
            // 数据绑定
            bindingContext.bindValue(observeTextMyNametextObserveWidget, namePersonObserveValue, null, null);
            // 调用IObservableValue.setValue方法修改数据对象的值,Text的内容会同步更新
            namePersonObserveValue.setValue("word");
            // 直接调用Person.setName方法来修改数据对象,Text不同步更新。
            person.setName("word")

    这不就行了?将POJO对象封装起来提供IObservableValue,所有的Set方法IObservableValue.setValue方法来实现,后续修改POJO对象改为调用这个封装对象的Set方法,不就可以实现POJO对象的数据的监控了吗?  关键是在我这个项目里这样做的成本并不高,只是后续要改变一下对POJO对象的访问方式而已。于是根据这个思路,我写了一个稍通用化的POJO封装类来实现这个想法儿:  分两个类

    ObservablePojoType 对POJO类进行可监控封装,为类的每个属性创建对应的{@link IBeanValueProperty}  ObservablePojoObject 对POJO对象进行可监控封装,为对象的每个属性创建对应的{@link IObservableValue}, 提供 setValuegetValue方法实现对POJO对象进行访问  ObservablePojoType.java

    package testwb;
    
    import java.beans.PropertyDescriptor;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    import org.eclipse.core.databinding.beans.IBeanValueProperty;
    import org.eclipse.core.databinding.beans.PojoProperties;
    import org.eclipse.core.databinding.observable.value.IObservableValue;
    import net.gdface.utils.Assert;
    import net.gdface.utils.BeanPropertyUtils;
    
    /**
     * 对POJO类进行可监控封装,为POJO类的每个属性创建对应的{@link IBeanValueProperty}
     * @see {@link PojoProperties#value(String)}
     * @see {@link IBeanValueProperty#observe(Object)}
     * @author guyadong
     *
     * @param <T> 封装的POJO类
     */
    public class ObservablePojoType<T> {
        private final Class<T> pojoType;
        private Map<String,IBeanValueProperty> ivalueProperties=new HashMap<String, IBeanValueProperty>();
        private final Map<String, PropertyDescriptor> propertyDescriptors;
        public ObservablePojoType(Class<T> pojoType) {
            if(null==pojoType)
                throw new NullPointerException();
            this.pojoType=pojoType;
            // 返回所有可读写的属性
            propertyDescriptors=BeanPropertyUtils.getProperties(pojoType, 3);
        }
        public ObservablePojoType(T pojo) {
            this((Class<T>) pojo.getClass());
        }
        /**
         * 返回POJO类的所有属性名
         * @return
         */
        public Set<String> getPropertyNames() {
            return propertyDescriptors.keySet();
        }
        /**
         * 返回source对象的指定属性(propertyName)的{@link IObservableValue}对象
         * @param source 监控目标对象
         * @param propertyName 属性名
         * @return
         */
        public IObservableValue<T> observe(T source,String propertyName) {
            if(null==source)http://www.90168.org/
                throw new NullPointerException();
            if(null==propertyName||propertyName.empty())
                throw new IllegalArgumentException();
            if(!propertyDescriptors.containsKey(propertyName))
                throw new IllegalArgumentException(String.format("invalid propertyName:%s",propertyName));
            if(!ivalueProperties.containsKey(propertyName)){
                ivalueProperties.put(propertyName, PojoProperties.value(propertyName));
            }
            return ivalueProperties.get(propertyName).observe(source);
        }
    
        /**
         * 返回指定对象的监控对象{@link ObservablePojoObject}
         * @param source
         * @return
         */
        public ObservablePojoObject<T> observe(T source){
            return new ObservablePojoObject<T>(source,this);
        }
    
        public PropertyDescriptor[] getPropertyDescriptors() {
            return propertyDescriptors.values().toArray(new PropertyDescriptor[0]);
        }
    }
    

    ObservablePojoObject.java

    package testwb;
    
    import java.beans.PropertyDescriptor;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.eclipse.core.databinding.observable.value.IObservableValue;
    import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
    
    /**
     * 对POJO对象进行可监控封装,为对象的每个属性创建对应的{@link IObservableValue}<br>
     * {@link #setValue(String, Object)}和 {@link #getValue(String)}实现对POJO对象进行访问<br>
     * 当调用 {@link #setValue(String, Object)}改变对象的属性值时,会自动通知监控对象<br>
     * 
     * 这里将普通的Java bean(有get/set方法但没有通过PropertyChangeSupport实现属性监控)定义为POJO对象
     * @author guyadong
     *
     * @param <T> 封装的POJO类
     */
    public class ObservablePojoObject<T> {
        private final T pojo;
        private final ObservablePojoType<T> pojoType;
        /**
         * 每个属性对应的{@link IObservableValue}
         */
        private final Map<String,IObservableValue> observableValues=new HashMap<String, IObservableValue>();
        public ObservablePojoObject(T pojo,ObservablePojoType<T> pojoType) {
            if(null==pojo)http://www.90168.org/
                throw new NullPointerException();
            this.pojo = pojo;
            this.pojoType = null==pojoType?new ObservablePojoType<T>((Class<T>) pojo.getClass()):pojoType;
        }
    
        public ObservablePojoObject(T pojo) {
            this(pojo,null);
        }
        /**
         * 返回指定属性对应的{@link IObservableValue}对象
         * @param propertyName
         * @return
         */
        public IObservableValue getObservableProperty(String propertyName){     
            if(!pojoType.getPropertyNames().contains(propertyName))
                throw new IllegalArgumentException(String.format("invalid propertyName:%s",propertyName));
            if(!observableValues.containsKey(propertyName)){
                observableValues.put(propertyName, pojoType.observe(pojo, propertyName));
            }
            return observableValues.get(propertyName);
        }
        /**
         * 设置指定属性的值
         * @param propertyName
         * @param value
         */
        public void setValue(String propertyName,Object value){
            getObservableProperty(propertyName).setValue(value);
        }
        /**
         * 获取指定属性的值
         * @param propertyName
         * @return
         */
        public Object getValue(String propertyName){
            return getObservableProperty(propertyName).getValue();
        }
        public T getPojo() {
            return pojo;
        }
        /**
         * 用from对象更新当前监控对象的所有属性
         * @param from
         * @return
         * @see #setValue(String, Object)
         * @see {@link BeanPropertyHelper#readProperty(Object, PropertyDescriptor)}
         */
        public ObservablePojoObject<T> updateFrom(T from){
            if(null==from)
                throw new NullPointerException();
            for(PropertyDescriptor propertyDescriptor:pojoType.getPropertyDescriptors()){
                setValue(propertyDescriptor.getName(), BeanPropertyHelper.readProperty(from, propertyDescriptor));
            }
            return this;        
        }
    }
    

    测试代码:  TestPojoBinding4.java

    package testwb;
    
    import org.eclipse.jface.dialogs.Dialog;
    import org.eclipse.jface.dialogs.IDialogConstants;
    import org.eclipse.swt.graphics.Point;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Control;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.widgets.Text;
    
    import org.eclipse.core.databinding.DataBindingContext;
    import org.eclipse.core.databinding.observable.value.IObservableValue;
    import org.eclipse.jface.databinding.swt.WidgetProperties;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.core.databinding.observable.Realm;
    import org.eclipse.jface.databinding.swt.DisplayRealm;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.events.SelectionAdapter;
    import org.eclipse.swt.events.SelectionEvent;
    
    public class TestPojoBinding4 extends Dialog {
    
        /**
         * 数据对象定义
         * @author guyadong
         *
         */
        public class Person {
            private String name;
            public Person(String name) {
                super();
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
                System.out.printf("updated %s
    ",this.name);
            }
        }
        private DataBindingContext m_bindingContext;
        /**
         * 成员变量:数据对象
         */
        protected Person personBak=new Person("hello!");
        protected Person person=new Person("hello!");
        private Text myNametext;
        private final ObservablePojoObject<Person> observablePersion=new ObservablePojoObject<Person>(person);;
    
        /**
         * Create the dialog.
         * @param parentShell
         */
        public TestPojoBinding4(Shell parentShell) {
            super(parentShell);
        }
    
        /**
         * Create contents of the dialog.
         * @param parent
         */
        @Override
        protected Control createDialogArea(Composite parent) {
            Composite container = (Composite) super.createDialogArea(parent);
            container.setLayout(null);
            Button btnNewButton = new Button(container, SWT.NONE);
            btnNewButton.addSelectionListener(new SelectionAdapter() {
                @SuppressWarnings("unchecked")
                @Override
                public void widgetSelected(SelectionEvent e) {
                    // 修改 person的name属性
                    observablePersion.setValue("name", "word");
                }
            });
            btnNewButton.setBounds(38, 154, 80, 27);
            btnNewButton.setText("测试");
    
            myNametext = new Text(container, SWT.BORDER);
            myNametext.setBounds(38, 27, 80, 23);
    
            Button btnNewButton_1 = new Button(container, SWT.NONE);
            btnNewButton_1.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    // 修改 person的name属性
                    observablePersion.updateFrom(personBak);
                }
            });
            btnNewButton_1.setBounds(132, 154, 80, 27);
            btnNewButton_1.setText("恢复");
    
            return container;
        }
    
        /**
         * Create contents of the button bar.
         * @param parent
         */
        @Override
        protected void createButtonsForButtonBar(Composite parent) {
            createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
            createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
            m_bindingContext = initDataBindings();
        }
    
        /**
         * Return the initial size of the dialog.
         */
        @Override
        protected Point getInitialSize() {
            return new Point(362, 298);
        }
        public static void main(String[] args) {
            Display display = Display.getDefault();
            Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
                public void run() {
                    try {
                        TestPojoBinding4 setting = new TestPojoBinding4(null);
                        setting.open();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        protected DataBindingContext initDataBindings() {
            DataBindingContext bindingContext = new DataBindingContext();
            IObservableValue observeTextMyNametextObserveWidget = WidgetProperties.text(SWT.Modify).observe(myNametext);
            // 数据绑定
            bindingContext.bindValue(observeTextMyNametextObserveWidget, observablePersion.getObservableProperty("name"), null, null);
            //
            return bindingContext;
        }
    }
  • 相关阅读:
    贝塞尔曲线
    行为树
    Astar寻路算法
    vuex入门
    关于用户留存率的计算的几个层次-费元星
    linux命令执行返回值(附错误对照表)费元星
    rabbitmqadmin安装与使用
    分布式锁服务 分布式协调系统
    记录一次使用react异步不更新数据的问题
    从0到1搭建前端异常监控系统(Vue + Webpack + Node.js + Egg.js + Jest)
  • 原文地址:https://www.cnblogs.com/tianshifu/p/6214848.html
Copyright © 2011-2022 走看看