定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知,并自动更新
观察者模式的使用场景
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
区别是观察者模式里面目标类维护了所有观察者的引用,而回调里面只是维护了一个引用。