`
绿窗明月
  • 浏览: 3307 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

基于Observer及Observable实现更易用的观察者模型

 
阅读更多

java提供了Observer接口和Observable类,可以很容易实现一个对象对另一个对象的观察。但同时也存在一些问题,至少个人是这么认为的:

  1. observer对observable的观察行为是由前者发出,而原生java中的这种关系是由Observable的addObserver方法来建立的。虽然观察者模型中大概就是这么描述的,但总感觉有些别扭。比如我要看一个美女,总不能由她来确定我是否可以观察她吧。
  2. 原生的被观察者需要继承Observable类,但是被观察者也需要继承其他类时就会出现冲突。如果把Observable实例作为一个属性,因为setChange方法是protect无法调用,会导致notifyObservers方法执行失败。当然总有解决办法,这个不得不说是一个问题。
  3. 在observer和observable建立关系后,需要observer的update方法来响应observable的行为。update方法有两个参数Observable o, Object arg,当observable存在多个不同场合触发动作时,observer只能通过第二个参数来判断动作类型以做响应,不太方便。

为了解决以上问题,基于Observer接口和Observable类实现了一套观察者模式的代码。先贴一下使用方法:

  1. 被观察者。需要定义一个observable属性,用以执行Observable职责。
    package com.hulkdeng.test;
    
    import com.hulkdeng.observe.Observable;
    import com.hulkdeng.observe.Observables;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class ObservableDemo {
    
        private Observable observable;
    
        public ObservableDemo() {
            //注册可名为hulk的可观察对象
            observable = Observables.register("hulk", this);
        }
    
        public void smash() {
            Map<String, Object> props = new HashMap<String, Object>();
            //为事件添加属性
            props.put("power", 100000);
            //触发名为smash的事件,并携带props参数
            observable.fire("smash", props);
        }
    }
    

  2. 观察者。同样需要定义一个observer属性,用以执行Observer职责。
    package com.hulkdeng.test;
    
    import com.hulkdeng.observe.*;
    
    //观察者需要实现ObserveSupport接口
    public class ObserverDemo implements ObserverSupport {
    
        private Observer observer;
    
        public ObserverDemo() {
            //注册观察者
            observer = Observers.register(this);
            //观察名为hulk的对象
            observer.observe("hulk");
        }
    
        @Override
        public void update(Event event) {
            //sourceName为被观察者的注册名(hulk),eventName是当前事件名称(smash)
            String sourceName = event.getSourceName(), eventName = event.getEventName();
            //获取事件的属性
            Integer power = event.getProp("power");
            //获取被观察对象
            ObservableDemo observableDemo = Observables.getSource("hulk");
        }
    }
    

以下依次介绍所使用的代码:

  1. Event类。封装了被观察者信息及自定义属性,用以替换原版中的notifyObservers方法中第二个参数Object arg。
    package com.hulkdeng.observe;
    
    import java.util.Map;
    
    public class Event {
        private String sourceName;
        private String eventName;
        private Map<String, Object> props;
    
        public Event(String sourceName, String eventName) {
            this.sourceName = sourceName;
            this.eventName = eventName;
        }
    
        public Event(String sourceName, String eventName, Map<String, Object> props) {
            this.sourceName = sourceName;
            this.eventName = eventName;
            this.props = props;
        }
    
        public String getSourceName() {
            return sourceName;
        }
    
        public String getEventName() {
            return eventName;
        }
    
    
        public <T> T getProp(String key) {
            return props != null ? (T) props.get(key) : null;
        }
    }
    

  2. Observable接口。专门用于触发操作的接口。
    package com.hulkdeng.observe;
    
    import java.util.Map;
    
    public interface Observable {
        void fire(String name);
    
        void fire(String name, Map<String, Object> props);
    }
    

  3. Observables类。用于集中管理被观察者的,其中包含ObservableBridge内部类,扩展优化了原始Observable并实现了上边的Observable接口。
    package com.hulkdeng.observe;
    
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Observables {
    
        private static Map<String, ObservableBridge> observableObjects = new HashMap<String, ObservableBridge>();
    
        public static Observable register(String name, Object source) {
            ObservableBridge bridge = new ObservableBridge(name, source);
            observableObjects.put(name, bridge);
            return bridge;
        }
    
        public static java.util.Observable get(String name) {
            return observableObjects.get(name);
        }
    
        public static <T> T getSource(String name) {
            return (T) observableObjects.get(name).getSource();
        }
    
        public static boolean contains(String name) {
            return observableObjects.containsKey(name);
        }
    
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public static class ObservableBridge extends java.util.Observable implements Observable {
            private String sourceName;
            private Object source;
    
            private ObservableBridge(String sourceName, Object source) {
                this.sourceName = sourceName;
                this.source = source;
            }
    
            public String getSourceName() {
                return sourceName;
            }
    
            public Object getSource() {
                return source;
            }
    
            @Override
            public void fire(String name) {
                setChanged();
                notifyObservers(new Event(sourceName, name));
            }
    
            @Override
            public void fire(String name, Map<String, Object> props) {
                setChanged();
                notifyObservers(new Event(sourceName, name, props));
            }
        }
    
    }
    

    
    
  4. Obsever类。专门用于执行observe操作的一个中间类。
    package com.hulkdeng.observe;
    
    public class Observer {
        private Observers.ObserverBridge observerBridge;
    
        public Observer(ObserverSupport observer) {
            this.observerBridge = new Observers.ObserverBridge(observer);
        }
    
        public void observe(String name) {
            if (Observables.contains(name)) {
                Observables.get(name).addObserver(observerBridge);
            }
        }
    }
    

  5. Obsevers类。结合上边的Obsever类及其内部类ObseverBridge实现了观察者observe方法和update方法的分离和扩展。
    package com.hulkdeng.observe;
    
    import java.util.Observable;
    
    public class Observers {
        public static Observer register(ObserverSupport observer) {
            return new Observer(observer);
        }
    
    
        public static class ObserverBridge implements java.util.Observer {
            private ObserverSupport observer;
    
            public ObserverBridge(ObserverSupport observer) {
                this.observer = observer;
            }
    
            /**
             * This method is called whenever the observed object is changed. An
             * application calls an <tt>Observable</tt> object's
             * <code>notifyObservers</code> method to have all the object's
             * observers notified of the change.
             *
             * @param o   the observable object.
             * @param arg an argument passed to the <code>notifyObservers</code>
             */
            @Override
            public void update(Observable o, Object arg) {
                observer.update((Event) arg);
            }
        }
    }
    
  6. ObseverSupport接口。专门执行观察者update方法的接口。
    package com.hulkdeng.observe;
    
    public interface ObserverSupport {
        void update(Event event);
    }
    

    以上代码都是用于个人项目,没有经过大规模验证,纯粹是为实现个人思想而作,还有很多纰漏。仅供大家参考娱乐

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics