设计模式-观察者模式

151 阅读3分钟

设计模式-观察者模式

一、应用场景

观察者模式一般用于,一个对象的更新(被观察者)需要同步给其他对象(观察者)。

二、设计思想

被观察者不应该知道观察者拿到数据后,是怎么处理数据的。他只需要和被观察者之间商量一个数据(推更新)或者一个接口(拉更新)。每次更新的时候将这个数据或者接口传递给观察者,由观察者负责处理这个数据或者通过这个接口拉取数据。观察者不应该知道被观察者对象是怎么更新的,他只应该关注在拿到更新的数据后应该做的处理

三、代码实现

被观察者对象 观察者每次调用set的时候都去notify他的observers。

    class Observable{
        private int data;
        private List<Observer> observers;
        Observable(int data){
            this.data = data;
            this.observers = new ArrayList();
        }
        void getData(){
            return data;
        }
        void setData(int data){
            this.data = data;
            notify();
        }
        void addObserver(Observer observer){
            this.observers.add(observer);
        }
        void removeObserver(Observer observer){
            observers.remove(observer);
        }
        private void notify(){
            for(observer:observers){
                observer.update(data);
            }
        }
    }

观察者接口

interface Observer {
    void update(int data);
}

观察者类
class FirstObserverImpl implements Observer {
    @Override 
    void updata(int data){
        if(data>60){
            System.out.println("data is bigger than 60")
        }
        else{
            System.out.println("data is not bigger than 60")
        }
    }
}

四、其他知识

推模型与拉模型
推模型为每次观察者就会将自己的所有数据传递给被观察者。适用于被观察者每次更新都需要观察者马上知晓的情况 拉模型为每次观察者只是将访问自己数据的一个接口暴露给了被观察者,观察者后续可以通过这个接口来访问观察者的数据。

五、思考问题

问题一

这里有一个问题,根据类的设计的单一职责原则,Observable对象只应该负责更新数据并且在数据发生变化时去通知所有的observers。他不应该去关心他自己的这一次更新是不是应该去通知Observers)。但是这有可能会造成浪费,假如被观察者和观察者之间的通信比较耗时(例如服务端和客户端之间的通信),是不是应该对数据的变化做一层判断。只认为有必要通知时,再去通知。但是这么做,可维护性比较差,你能保证这个数据更新对已有的观察者是可以过滤的,但是如何保证以后所有的观察者都能满足这个条件呢。因此从设计模式的角度来说,这是不符合规范的。我自己想到的比较好的解决办法就是,每个观察者对象内部包含一个类,叫Filter,定义了什么时候应该通知到他的逻辑。被观察者在通知前,对filter进行判断后再进行notify。

     class Observable{
        private int data;
        private List<Observer> observers;
        Observable(int data){
            this.data = data;
            this.observers = new ArrayList();
        }
        void getData(){
            return data;
        }
        void setData(int data){
            this.data = data;
            notify();
        }
        void addObserver(Observer observer){
            this.observers.add(observer);
        }
        void removeObserver(Observer observer){
            observers.remove(observer);
        }
        private void notify(){
            for(observer:observers){
                if(observer.filter.filterData(data){
                    observer.update(data);
                }
            }
        }
    }

被观察者类

interface Observer {
    void update(int data);
}
interface Filter{
    boolean filterData(int data)
}
class FirstObserverImpl implements Observer {
    public Filter filter;
    Observer(){
        this.filter = new Filter(){
            @Override 
            filterData(int data){
                if(data>60){
                    return true;
                }
                else{
                    return false;
                }
            }
        }
    }
    @Override 
    void updata(int data){
        System.out.println(String.valueOf(data));
    }
    
}

问题二

拉更新提供个接口,和把接口能力保存在观察者中,被观察者发生变化时,只是notify观察者对象,我发生变化了,是否就行,不过和传一个接口也没本质区别