观察者模式(Observer Pattern)
定义对象间的一(Observable)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。
Observer模式要解决的问题为:建立一个一(Observable)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。列举一个开发中简单的例子:假如有三个Activity,依次打开三个Activity,当在第三个Activity中改变了某一数据,使前面两个目前不可见的Activity中的数据也得到同步的改变。Observer模式就是解决了这一个问题。
因此我们知道,观察者模式中主要有观察者和被观察者2个对象,而在观察模式中Observable表示被观察者,或者用Subject(主体)表示,由于这个对象是一个抽象类,所以只能被继承。而Observer表示观察者,它并不是一个类而是一个接口,所以观察者可以有多个,实现了该接口的类都属于观察者。 当然有人会问既然被观察者是一个抽象类而观察者是一个接口,那么是否有一个类即继承Observable类又实现Observer接口呢,这个自然可以,观察者当然也可以同时是被观察者,被观察者同样可以是观察者,在这里完全不冲突。
观察者模式的参与者:
- Observable(被观察者)
- 被观察者知道有哪些观察者在观察自己,可以有任意多个观察者观察同一个被观察者
- 提供添加、删除、通知观察者对象的接口
- Observer(观察者)
- 为那些在被观察者发生改变时需获得通知的对象定义个更新的接口
- ConcreteObservable(具体被观察者)
- 当它的状态发生改变时,向它的各个观察者发出通知
- ConcreteObserver(具体观察者,在我的例子中是MainActivity、SecondActivity、ThirdActivity)
- 实现Observer的更新接口使自身状态与被观察者的状态保持一致
我们先来看下效果图:
运行demo首先进入MainActivity,点击button进入SeconActivity,再点击button进入ThirdActivity,点击button刷新数据,可以看到ThirdActivity中的文字内容改变,按一次返回键回到SecondActivity,可以看到其文字内容页同步改变,再按一次返回键到MainActivity中,其文字内容也同步改变
我们再来看下代码的具体实现:
源码点击这里(移步GitHub)
源码点击这里(移步GitHub)
1.一个Observable接口及其实现类
public interface IObservable {
//增加观察者
void addObserver(IObserver observer);
//删除观察者
void remove(IObserver observer);
//通知所有的观察者
void notifyObservers(String content);
//自身的操作
void operation(String content);
}
public abstract class AObservable implements IObservable {
//观察者的集合
private ArrayList
observers = new ArrayList<>();
//添加观察者到集合
@Override
public void addObserver(IObserver observer) {
observers.add(observer);
}
//从集合中删除观察者
@Override
public void remove(IObserver observer) {
if(observers.contains(observer)) {
observers.remove(observer);
}
}
//通知所有的观察者
@Override
public void notifyObservers(String content) {
for (IObserver observer : observers) {
observer.update(content);
}
}
}
2.ConcreteObservable
public class ConcreteObservable extends AObservable {
private static ConcreteObservable observable;
//单例
public static ConcreteObservable getInstance(){
if(null == observable) {
synchronized (AObservable.class){
if( null == observable) {
observable = new ConcreteObservable();
}
}
}
return observable;
}
@Override
public void operation(String content) {
notifyObservers(content);
}
}
3.一个Observer接口
public interface IObserver {
//刷新数据
void update(String content);
}
4.ConcreteObserver
public class MainActivity extends AppCompatActivity implements IObserver{
TextView tv_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_main = (TextView)findViewById(R.id.tv_main);
findViewById(R.id.btn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
//添加观察者到被观察者的被订阅列表,简称:订阅
ConcreteObservable.getInstance().addObserver(this);
}
@Override
public void update(String content) {
tv_main.setText(content);
}
}
public class SecondActivity extends AppCompatActivity implements IObserver{
TextView tv_second;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
tv_second = (TextView)findViewById(R.id.tv_second);
findViewById(R.id.btn_second).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
startActivity(intent);
}
});
//订阅
ConcreteObservable.getInstance().addObserver(this);
}
@Override
public void update(String content) {
tv_second.setText(content);
}
}
public class ThirdActivity extends AppCompatActivity implements IObserver {
TextView tv_third;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
tv_third = (TextView)findViewById(R.id.tv_third);
findViewById(R.id.btn_third).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//被观察者有了动作
ConcreteObservable.getInstance().operation("数据被刷新了");
}
});
//订阅
ConcreteObservable.getInstance().addObserver(this);
}
@Override
public void update(String content) {
tv_third.setText(content);
}
}