观察者模式Observer和Observable
简述
观察者模式类广播一对多的模式传递消息,为了直观的解释这个模式,直接手写一个观察者模式的整体代码吧
手写观察者模式
1.创建观察者接口
观察者是来观察变化的,所以,观察者属于数据变更之后被动收到消息做出动作的这个对象,那么,这个接口就是扩展观察者的能力,让其拥有做动作的能力
public interface myObserver {
void update(myObservable myObservable,Object obj);
}
其实看到这个接口肯定就能想到是观察者继承了接口,然后在变化时,这个接口中的这个update方法被调用了
2.创建被观察者(建议理解为数据,方便弄清楚概念)
根据上述,在变化时,这个接口中的这个update方法被调用了,(暂时简单理解为数据变化了),那么,被观察者首先应该要持有观察者对象,上面说到类似广播,于是是有可能会持有很多个观察者,再考虑到后面需要由观察者调用上面接口中的方法,应该有一个集合储存观察者,这是一部分,接着,观察者应该是被添加进来的,就有添加方法,同样删除的方法,最重要的,得有通知的方法,也就是说,数据变化,数据调通知方法,方法中遍历观察者,调用观察者对象的扩展接口的方法让其拥有做动作的能力(更新状态)
至于加锁什么的在代码中有注释
上代码
package com.example.objecttest;
import java.util.Vector;
public class myObservable {
//vector是一个线程安全的集合,缺点是速度较慢,它用来储存观察者对象
private final Vector<myObserver> myObservers;
private boolean changed = false;
//构造方法
public myObservable() {
myObservers = new Vector<>();
}
//添加观察者,这个方法需要加锁
public synchronized void addObserver(myObserver observer) {
if (observer == null) {
throw new NullPointerException("observer is null");
}
if (!myObservers.contains(observer)) {
myObservers.addElement(observer);//按照先后循序一次添加
}
}
//删除观察者
public synchronized void deleteObserver(myObserver observer) {
myObservers.remove(observer);
}
//删除所有观察者
public synchronized void deleteAllObserver() {
myObservers.clear();
}
//统计所以得observer
public synchronized int countAllObservers() {
return myObservers.size();
}
//提供一个方法通知变化观察着
public void notifyObserver() {
notifyObserver(null);
}
public void notifyObserver(Object o) {
Object[] observerObject = null;
//为了防止在通知的时候有新的观察着添加进来而错过
synchronized (this) {
//当外部手动添加并改变changed时
if (!hasChanged()) {
return;
}
//没有改变时
observerObject = myObservers.toArray();
clearChanged();
}
for (int i = observerObject.length - 1; i >= 0; i--) {
//逐个遍历观察着,调用upDate方法
((myObserver) observerObject[i]).update(this, o);
}
}
private void clearChanged() {
changed = false;
}
private boolean hasChanged() {
return changed;
}
public void setChanged() {
changed = true;
}
}
3.使用示例
上代码
创建被观察者
package com.example.objecttest;
//被观察者(数据)
public class Message extends myObservable {
public void messageHasChanged(String message) {
setChanged();//这个方法设置进去会使得在notify的时候不会进入if循环走return
notifyObserver(message);//通知刷新
}
}
创建观察者
package com.example.objecttest;
import android.util.Log;
import java.util.Observable;
import java.util.Observer;
//观察者实现接口,重写方法,扩展能力
public class Person implements myObserver {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public void update(myObservable myObservable, Object obj) {
//业务操作
Log.e("len.hu",name + "收到了" + obj.toString() + "消息");
}
}
Acitvity中的使用
package com.example.objecttest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建观察者,人观察数据
Person p1 = new Person("小虎");
Person p2 = new Person("飘飘");
Person p3 = new Person("图图");
Person p4 = new Person("爷爷");
//创建被观察者,比如说数据
Message message = new Message();
//将二者关联起来
message.addObserver(p1);
message.addObserver(p2);
message.addObserver(p3);
message.addObserver(p4);
//假设数据变更
message.messageHasChanged("今天中午吃饭了没有");
}
}
日志结果打印
至于这个为什么是倒序,看看上面的代码就好了