概念
观察者模式是 23 种设计模式中的一种。它定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。
观察者模式存在的意义就是「解耦」,它使观察者和被观察者的逻辑不再搅和在一起,而是彼此独立、互不依赖。
观察者模式简单代码示例
定义被观察者(Observable)接口
public interface ObservableImpl {
// 注册一个观察者
void registerObserver(Observer observer);
// 移除一个观察者
void removeObserver(Observer observer);
// 通知注册的观察者更新
void notifyObserver();
}
实现具体的被观察者
public class Observable implements ObservableImpl{
// 定义集合用来存放每一个注册进来的观察者
private List<Observer> observers = null;
// 被观察者当前状态
public String ObservableState = "0";
public Observable() {
if (observers == null)
observers = new ArrayList<>();
}
// 注册观察者
@Override
public void registerObserver(Observer observer) {
if (observers != null)
observers.add(observer);
}
// 移除观察者
@Override
public void removeObserver(Observer observer) {
if (observers != null || observers.size() != 0)
observers.remove(observer);
}
// 通知所有注册的观察者进行更新
@Override
public void notifyObserver() {
if (observers == null || observers.size() == 0)
return;
for (Observer o: observers) {
o.update();
}
}
public void setObservableState(String observableState) {
ObservableState = observableState;
notifyObserver();
}
}
定义观察者(Observer)接口
public interface ObserverImpl {
void update();
}
实现具体观察者类
public class Observer implements ObserverImpl {
private String observerState = "0"; // 观察者初始状态
private String name; // 当前观察者名称
private Observable observable;
// 被观察者把自己传给观察者,当状态改变时,通知列表中的观察者
public Observer(String name, Observable observable) {
this.name = name;
this.observable = observable;
System.out.println("我是观察者" + name + "我的初始化状态是" + observerState);
}
// 当被观察者状态改变,观察者需要随之改变
@Override
public void update() {
observerState = observable.ObservableState;
System.out.println("我是观察者" + name + "我的初始化状态是" + observerState);
}
}
前端调用打印
public class Test {
public static void main(String[] args) {
Observable observable = new Observable();
observable.registerObserver(new Observer("A", observable));
observable.registerObserver(new Observer("B", observable));
observable.registerObserver(new Observer("C", observable));
observable.setObservableState("1");
}
}
打印日志
我是观察者A我的初始化状态是0
我是观察者B我的初始化状态是0
我是观察者C我的初始化状态是0
我是观察者A我的初始化状态是1
我是观察者B我的初始化状态是1
我是观察者C我的初始化状态是1
Android 中实现值传递
在 Android 开发中,我们经常会遇到 Activity 与 Fragment 之间的传值,或者 Fragment 与 Fragment 之间的传值。我们会想到想到广播、接口回调等一些办法,下面会介绍通过观察者模式来实现值传递。具体实现步骤如下
定义被观察者接口
public interface ObservableImpl {
void registerObserver(ObserverImpl observer);
void removeObserver(ObserverImpl observer);
void notifyObserver();
}
实现被观察者实现类
public class Observable implements ObservableImpl {
private List<ObserverImpl> observers = null;
public String state = "";
public Observable() {
if (observers == null)
observers = new ArrayList<>();
}
@Override
public void registerObserver(ObserverImpl observer) {
if (observers != null)
observers.add(observer);
}
@Override
public void removeObserver(ObserverImpl observer) {
if (observer != null || observers.size() != 0)
observers.remove(observer);
}
@Override
public void notifyObserver() {
if (observers == null || observers.size() == 0)
return;
for (ObserverImpl observer : observers) {
observer.update(state);
}
}
public void setState(String state) {
this.state = state;
notifyObserver();
}
}
观察者接口,就是一个通知刷新的简单方法
public interface ObserverImpl {
void update(String title);
}
在 Fragment 中实现观察者接口
public class MyFragment extends Fragment implements ObserverImpl{
private View view;
private TextView textView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_view, container, false);
textView = view.findViewById(R.id.title);
return view;
}
// 当 Activity 中的数据发生变化时,被观察者会调用刷新通知 Fragment 刷新
@Override
public void update(String title) {
textView.setText(title);
}
}
在 Activity 中通过创建被观察者实例,注册添加观察者,当 Activity 中数据变化时,调用被观察者数据更新,被观察者会循环遍历注册的观察者进行刷新。
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private int count = 0;
private Observable observable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = (ViewPager) findViewById(R.id.viewPager);
List<Fragment> fragments = new ArrayList<>();
MyFragment fragment1 = new MyFragment();
final MyFragment fragment2 = new MyFragment();
fragments.add(fragment1);
fragments.add(fragment2);
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager(), fragments));
// 创建被观察者实例
observable = new Observable();
// 注册观察者
observable.registerObserver(fragment1);
observable.registerObserver(fragment2);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
count = count + 1;
if (count == 5) {
observable.removeObserver(fragment2);
}
// 这值传递太爽了,就这么简单,还使 Activity 和 Fragment 实现的高度解耦
observable.setState(String.valueOf(count));
}
});
}
class MyAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
}
总结
在使用观察者模式中,每个观察者需要被保存到被观察者的集合中,被观察者通过注册添加或移除的方式操作观察者。当被观察者的状态发生改变,通过遍历或循环的方式通知列表中注册的观察者进行更新操作。该模式解耦了观察者和被观察者之间的依赖,使得各自的变化对另一方影响较小。