Android常用设计模式-观察者模式

1,032 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Android中的观察者模式

观察者模式也是Android-Api中常用到的模式,它常用的地方是GUI系统、订阅——发布系统等,其模式重要特性就是解耦。

观察者模式的主要功能是让多个观察者同时监听某一个主题的变化,当监听的主题发生了变化,会通知所有的观察者,使得它们能更新自己。

定义观察者模式我们可以自定义实现,也可以使用继承Api的方式来实现:

一、自定义实现

自定义Observable 被观察主题对象

public class Observable<T> {  
    List<Observer<T>> mObservers = new ArrayList<Observer<T>>();  
  
    public void register(Observer<T> observer) {  
        if (observer == null) {  
            throw new NullPointerException("observer == null");  
        }  
        synchronized (this) {  
            if (!mObservers.contains(observer))  
                mObservers.add(observer);  
        }  
    }  
  
    public synchronized void unregister(Observer<T> observer) {  
        mObservers.remove(observer);  
    }  
  
    public void notifyObservers(T data) {  
        for (Observer<T> observer : mObservers) {  
            observer.onUpdate(this, data);  
        }  
    }  
  
}

自定义Observer 观察者

public interface Observer<T> {  
    void onUpdate(Observable<T> observable,T data);  
}

其实就通用于所有的观察者与被观察者之间的关联了,比如我们想观察天气对象,我们监听天气发生了变化,通知给每一个观察者做更新。

定义一个天气对象

public class Weather {  
    private String description;  
  
    public Weather(String description) {  
        this.description = description;  
    }  
  
    public String getDescription() {  
        return description;  
    }  
  
    public void setDescription(String description) {  
        this.description = description;  
    }   
}

使用的时候:

        Observable<Weather> observable=new Observable<Weather>();  
        Observer<Weather> observer1=new Observer<Weather>() {   //直接构建出接口对象,匿名实现
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("观察者1:"+data.toString());  
            }  
        };  
        Observer<Weather> observer2=new Observer<Weather>() {  
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("观察者2:"+data.toString());  
            }  
        };  
  
        observable.register(observer1);  
        observable.register(observer2);  
  
  
        Weather weather=new Weather("晴转多云");  
        observable.notifyObservers(weather);  
  
        Weather weather1=new Weather("多云转阴");  
        observable.notifyObservers(weather1);  
  
        observable.unregister(observer1);  
  
        Weather weather2=new Weather("台风");  

打印

观察者1:Weather{description=’晴转多云’}
观察者2:Weather{description=’晴转多云’}
观察者1:Weather{description=’多云转阴’}
观察者2:Weather{description=’多云转阴’}
观察者2:Weather{description=’台风’}

二、继承Api的实现

Java的Api中就有观察者模式的定义 java.util.Observable 类和 java.util.Observer 接口,这分别对应着 Subject 和 Observer 的角色。

需要注意的是被观察者在调用 notifyObservers() 函数通知观察者之前一定要调用 setChanged() 函数,要不然观察者无法接到通知

例如我们定义一个被观察者 Observable

public class MyPerson extends Observable {

    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        setChanged();
        notifyObservers();
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        setChanged();
        notifyObservers();
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
        setChanged();
        notifyObservers();
    }

    @Override
    public String toString() {
        return "MyPerson [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }
}

定义一个观察者 Observer

public class MyObserver implements Observer {

    private int id;
    private MyPerson myPerson;

    public MyObserver(int id) {
        System.out.println("我是观察者---->" + id);
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public MyPerson getMyPerson() {
        return myPerson;
    }

    public void setMyPerson(MyPerson myPerson) {
        this.myPerson = myPerson;
    }

    @Override
    public void update(Observable observable, Object data) {
        System.out.println("观察者---->" + id + "得到更新");
        this.myPerson = (MyPerson) observable;
        System.out.println(((MyPerson) observable).toString());
    }

}

通过 setChanged() 告知数据改变, 通过 notifyObservers() 发送信号通知观察者。

使用:

  MyObserver observable = new MyPerson() //被观察者

  observable.addObserver(new MyObserver(0));   //添加多个观察者
  observable.addObserver(new MyObserver(1)); 

  observable.setName("a" + i);  
  observable.setAge(10 + i);
  observable.setSex("男" + i);

  //被观察者内部每一个set方法内部都做了setChanged(); notifyObservers(); 所以观察者可以收到消息,观察者的update()方法可以正常收到消息,打印消息
        

总结

观察者模式在Android源码和一些第三方库都使用的比较广泛,如ListView RecyclerView BroadcastReceiver EventBus等。

使用场景为:当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。

注意点:
在使用时要考虑开发效率和运行效率,程序中包括一个被观察者、多个观察者、开发调试等内容会比较复杂,且Java中消息通知默认是顺序执行,如果一个观察者卡顿,那么会影响整体执行效率,在这种情况下一般考虑使用异步的方式。

好了简单的使用就到处为主,后面会将一些实用技巧哦