java 设计模式:观察者
1、概念
在对象之间定义了一对多的依赖,使得么当一个对象状态发生改变,其相关依赖对象会收到通知并自动更新。
2、场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面
- 一个对象的改变将导致一个或多个其他对象也发生改变
- 需要在系统中创建一个触发链
3、UML结构图分析
- 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
- 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
- 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
- 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
4、实际代码分析
实现观察者代码:
/**
*
* 创建观察者抽象类
*/
public interface Observer {
//更新方法
void update(String newStatus);
}
/**
* 创建观察者实现类
*/
public class ConcreteObserver implements Observer {
/**
* 观察者状态
*/
private String observerState;
@Override
public void update(String newStatus) {
observerState = newStatus;
System.out.println(newStatus);
}
}
/**
* 创建抽象目标者
* Created by shidawei on 2019/5/23.
*/
public abstract class Subject {
private List<Observer> mObservers = new ArrayList<>();
/**
* 注册观察
* @param observer
*/
public void attach(Observer observer){
mObservers.add(observer);
System.out.println("注册观察");
}
/**
* 移除观察者
* @param observer
*/
public void detach(Observer observer){
mObservers.remove(observer);
}
/**
* 通知观察者
* @param newStatus
*/
public void notifyObsercers(String newStatus){
for(Observer observer:mObservers){
observer.update(newStatus);
}
}
}
/**
* 实现被观察者
*/
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
public void change(String newState){
state = newState;
System.out.println(newState);
notifyObsercers(newState);
}
}
//测试代码
ConcreteSubject concreteSubject = new ConcreteSubject();
concreteSubject.attach(new ConcreteObsercer());
concreteSubject.attach(new ConcreteObsercer());
concreteSubject.attach(new ConcreteObsercer());
concreteSubject.change("123");
java内部的接口实现:
/**
* Observable 是被观察者对象接口,是对被观察者的实现
*/
public class TargetObervable extends Observable {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
//被观察者数据发生改变的时候通过如下两行代码通知所有观察者
this.setChanged();
this.notifyObservers();
}
}
/**
* Observer 对象是观察者,实现Observer的对象就是实现观察者对象
*/
public class TargetOberver implements Observer {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "收到数据变更" + ((TargetObervable) o).getMessage());
}
}
//测试代码
TargetObervable targetObervable = new TargetObervable();
targetObervable.addObserver(new TargetOberver());
targetObervable.addObserver(new TargetOberver());
targetObervable.addObserver(new TargetOberver());
targetObervable.setMessage("1234");
两种观察者对比:
通过读源码Observable.class我们得知对Observer的集合为Vector
Vector为线程安全的,会保证线程安全,但是性能差。可以采用CopyOnWriteArrayList来代替Vector。
观察者设计模式在Android中的实际运用
回调模式:一对一的模式
实现了抽象类/接口的实例实现了负累的提供的抽象方法,然后将该方法还给父类来处理。
Fragment与activity通信的代码实例:
/**
*回调接口,与activity通信
**/
public interface ISwitchCaoZuoRecordFragment {
void toSwitch(CaiZuoRecordFragFragment fragment, CaiZuoRecordFragPresenter presenterDecorator);
}
/**
* activity实现该接口
**/
public class CaoZuoRecordActivity extends BaseActivity<CaoZuoRecordView, CaoZuoRecordPresenter> implements CaoZuoRecordView ,CaiZuoRecordFragFragment.ISwitchCaoZuoRecordFragment{
@Override
public void toSwitch(CaiZuoRecordFragFragment fragment, CaiZuoRecordFragPresenter presenterDecorator) {
mPresenterDecorator = presenterDecorator;
if(presenterDecorator.studentName!=null&&!presenterDecorator.studentName.equals("")){
searchListTitleBar.getSearch().setText(presenterDecorator.studentName);
searchListTitleBar.getClear().setVisibility(View.VISIBLE);
searchListTitleBar.getSearch_layout().setVisibility(View.VISIBLE);
}else{
searchListTitleBar.getSearch().setText("");
searchListTitleBar.getClear().setVisibility(View.GONE);
searchListTitleBar.getSearch_layout().setVisibility(View.GONE);
}
}
/**
*fragment注册和取消
*/
@Override
public void onDetach() {
super.onDetach();
iSwitchCaoZuoRecordFragment = null;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof ISwitchCaoZuoRecordFragment) {
iSwitchCaoZuoRecordFragment = (ISwitchCaoZuoRecordFragment) context;
}else{
throw new RuntimeException(context.toString()
+ " 必须实现 ISwitchCaoZuoRecordFragment");
}
}