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;
        }
    }
  • 相关阅读:
    bzoj 4012: [HNOI2015]开店
    POJ 1054 The Troublesome Frog
    POJ 3171 Cleaning Shifts
    POJ 3411 Paid Roads
    POJ 3045 Cow Acrobats
    POJ 1742 Coins
    POJ 3181 Dollar Dayz
    POJ 3040 Allowance
    POJ 3666 Making the Grade
    洛谷 P3657 [USACO17FEB]Why Did the Cow Cross the Road II P
  • 原文地址:https://www.cnblogs.com/tianshifu/p/6214848.html
Copyright © 2011-2022 走看看