阅读 55

Java 观察者模式

定义

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知,并自动更新

观察者模式的使用场景

1 关联行为场景,需要注意的是,关联行为是可拆分的,而不是组合关系

2 时间多级触发场景

3跨系统的消息交换场景,例如,消息队列,事件总线的处理机制

观察者模式的UML图

这里写图片描述

这里写图片描述

下面来看一下一个小例子

老师和同学,同学要订阅老师,然后老师发布作业,同学就自动会收到老师的信息

//观察者

public interface Observer {

    public void updata(String work);

}1234567复制代码
//集体观察者
public class StudentObserver implements Observer {

    private final Subject mSubject;
    private String mName;
    private String mWork;

    public StudentObserver(String name, Subject subject) {
        this.mName = name;
        this.mSubject = subject;
        this.mSubject.registerObserver(this);

    }


    @Override
    public void updata(String work) {
        Log.d("mmmobserver", mName + "今天作业是" + work);
    }


}12345678910111213141516171819202122复制代码
//主题(被观察者)
public interface Subject {

    public void registerObserver(Observer observer);

    public void romoveObserver(Observer observer);

    public void nofityObserver();
}
12345678910复制代码
//具体被观察者
public class TeacherSubject implements Subject {

    private final ArrayList<Observer> mObservers;
    private String mWork;

    public TeacherSubject() {
        mObservers = new ArrayList<>();
    }


    @Override
    public void registerObserver(Observer observer) {

        mObservers.add(observer);

    }

    @Override
    public void romoveObserver(Observer observer) {

        if (mObservers.indexOf(observer)>=0){
            mObservers.remove(observer);
        }
    }

    @Override
    public void nofityObserver() {

        for (Observer o:mObservers) {
            o.updata(mWork);
        }
    }

    public void setHomework(String work){
        this.mWork=work;
        this.nofityObserver();
        Log.d("mmmsubject","今天作业是"+work);
    }
}12345678910111213141516171819202122232425262728293031323334353637383940复制代码

调用

public class ObserverActivity extends BaseActivity {

    @Override
    public int setMainView() {
        return R.layout.activity_observer;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setToobarTitle("观察者模式");
        TeacherSubject teacherSubject = new TeacherSubject();
        StudentObserver 张三 = new StudentObserver("张三", teacherSubject);
        StudentObserver 李四 = new StudentObserver("李四", teacherSubject);
        StudentObserver 王五 = new StudentObserver("王五", teacherSubject);

        teacherSubject.setHomework("第五页第一题");
        teacherSubject.setHomework("第五页第二题");
        teacherSubject.setHomework("第五页第三题");
    }
}123456789101112131415161718192021复制代码

界面显示

10-18 09:36:47.911 11947-11947/com.example.jh.rxhapp D/mmmobserver: 张三今天作业是第五页第一题
10-18 09:36:47.911 11947-11947/com.example.jh.rxhapp D/mmmobserver: 李四今天作业是第五页第一题
10-18 09:36:47.911 11947-11947/com.example.jh.rxhapp D/mmmobserver: 王五今天作业是第五页第一题
10-18 09:36:47.911 11947-11947/com.example.jh.rxhapp D/mmmsubject: 今天作业是第五页第一题
10-18 09:36:47.911 11947-11947/com.example.jh.rxhapp D/mmmobserver: 张三今天作业是第五页第二题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmobserver: 李四今天作业是第五页第二题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmobserver: 王五今天作业是第五页第二题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmsubject: 今天作业是第五页第二题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmobserver: 张三今天作业是第五页第三题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmobserver: 李四今天作业是第五页第三题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmobserver: 王五今天作业是第五页第三题
10-18 09:36:47.913 11947-11947/com.example.jh.rxhapp D/mmmsubject: 今天作业是第五页第三题

这样就达到目的了

我是做Android 的,如果做Android 的话就会知道有一个第三方EventBus,他就是典型的观察者模式,我在这里简单口述一下他的工作原理

EventBus.getDefault().register(this);这个注册会把 当前类也就是this(c),和 类中OnEvent开头的方法(m),和方法其中的参数(p),存到一个Map中,以p作为 key ,以c和m组成的对象作为 value;把这个map存起来,然后 EventBus.getDefault().post(new UpdateReplyEvent());的时候,以post中的参数从map中取出,c和m,再利用反射直接调用该方法就行,这就是大概原理,详细请看源码

现在说一下观察者模式和回调的区别

先看一个回调的例子,也是学生和老师

public interface CaStudent {

    public void onCallBack(String work);
}1234复制代码
public class CaTeacher {

    private CaStudent mCallback;

    //注册事件
    public void register(CaStudent callBack) {
        this.mCallback = callBack;
    }

    public void setWork(String work) {
        mCallback.onCallBack(work);
    }
}12345678910111213复制代码
public class ObserverActivity extends BaseActivity {

    @Override
    public int setMainView() {
        return R.layout.activity_observer;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setToobarTitle("观察者模式");
        CaTeacher caTeacher = new CaTeacher();
        caTeacher.register(new CaStudent() {
            @Override
            public void onCallBack(String work) {
                Log.d("mmmcallback", "今天作业是" + work);
            }
        });
     caTeacher.setWork("打游戏");
    }
}123456789101112131415161718192021复制代码

最后打印

10-19 03:13:51.924 5617-5617/com.example.jh.rxhapp D/mmmcallback: 今天作业是打游戏

这个就是我们经常用的回调,可以看出回调中Cateacher只维护了一个 CaStudent ,而 观察者中维护了一个list的student,所以回调其实是简单的观察者

   private final ArrayList<Observer> mObservers;

    public TeacherSubject() {
        mObservers = new ArrayList<>();
    }12345复制代码

区别是观察者模式里面目标类维护了所有观察者的引用,而回调里面只是维护了一个引用。


文章分类
Android