设计模式系列:
0.Android开发常用设计模式;
1. Android中单例模式;
2. Android中建造者(builder)模式;
3. Android中观察者模式;
4. Android中原型模式;
5. Android中策略模式;
6.Android中工厂模式;
7.Android中代理模式;
8.Android中装饰者模式;
9. Android中适配器模式;
小白:毛毛哥,最近我搜索网上资料看观察者模式有点晕晕的
三毛:“这个说明你对接口的理解和使用不熟,另外百度出来的资料一大堆要么只说一半,要么还是只说一半,当然还有小部分好的,只是你搜索的姿势不对”
三毛:”其实平常我们无处不接触观察者模式,像ListView、RecycerView…的item点击事件或普通控件(Button…)点击事件都使用了观察者模式,平常开发中界面A–>B–>C,然后要跟新A界面东西也可以使用观察者模式”
小白:奥~,我一直以为只是接口和接口回掉,没想过还有这个名字
三毛:”嗯,像平常的按钮点击事件监听,我给他加上名字,你就有点理解观察者模式的过程了,虽然Android系统给我们封装好了,但是不要紧,先看看,像下面”
//平常里的按钮事件监听例子
Button buttonA = (Button)findViewById(R.id.button1);
//注册观察者
buttonA.setOnClickListener(new OnClickListener()
{
//观察者实现
@Override
public void onClick(View view)
{
//这里可以知道要观察的对象的一举一动...
}
});
//拆分后
buttonA ---->要观察的对象//要观察谁谁谁
setOnClickListener() ---->观察者
new OnClickListener() ---->观察者的实现//在实现里可以知道要观察的对象的一举一动
三毛:“OK,我的白,我想问下你,’在A界面设置夜晚/白天模式,项目里所有已经打开的界面都要接收到通知(没打开的不管)’你有什么思路可以实现呢”
小白:我想到有几种方法
1)使用广播;
2)使用第三方框架Eventbus;
3)A设置好数据后保存到sharepreferences,,所有打开的界面都启动一个定时器,每2秒从sharepreferences获取一次数据。
三毛:“可以哇,白白,能想到那么多方法,不过最后一个方法简直乱来”
小白:啦啦啦~~~。
三毛:”1)广播不适用于发送大数据和频繁发送,因为当系统或应用发出广播时,将会扫描系统中的所有广播接收者,通过action匹配将广播发送给相应的接收者,接收者收到广播后将会产生一个广播接收者的实例,执行其中的onReceiver()这个方法,并且onReceive方法中不能执行太耗时的操作,也不要在里面创建子线程处理耗时操作(因为可能子线程没处理完,接收者就被回收了)”
2)对于Eventbus看这个为什么你应该停止使用EventBus
3)广播、EventBus、RxJava…很多热门的东西使用的都是观察者模式,只不过 他们使用场景要分清。
小白:握草,毛毛哥继续
观察者模式定义:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
三毛:”观察者模式按道理来说应该有2种,如下”
//第一种
JDK封装好了观察者设计模式的API支持:
1、java.util.Observable类//要观察的对象(继承该类)
2、java.util.Observer接口//观察者(new个类实现该接口)
3、要观察的对象通过setChanged()方法以及notifyObservers(Object)方法就可以通知观察者
//第二种
不使用JDK提供的API,自己实现(虽然有点造轮子的感觉,可是自己写能更加随心所欲,是不辣~~)
小白:奥,我终于知道为嘛毛毛哥说查到的资料都是只说一半一半的了
三毛:“嗯,我先用JDK提供的API模拟上面的‘在A界面设置夜晚/白天模式,项目里所有已经打开的界面都要接收到通知(没打开的不管)’”
先写个要观察谁的类
//要观察皮肤设置(谁)
public class SkinObservable extends Observable {
public void notificationUpdate(String content){
//通知更新前准备准备
setChanged();
//准备好了,开始通知更新
notifyObservers(content);
}
}
然后写观察者类
public class SkinObserverB implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("更新辣,内容是:"+arg);
}
}
//SkinObserverC,SkinObserverD,SkinObserverE...?
//多少个界面要更新皮肤就写多个个观察者,然后new出来?写一个放到基类就好了
设置皮肤就通知观察者更新
//1 创建要观察谁(对象)
SkinObservable skinObservable=new SkinObservable();
//2 创建观察者
SkinObserverB observerB=new SkinObserverB();
//3 将观察者注册到要观察对象的观察者列表中
skinObservable.addObserver(observerB);
//如果这样写(不就和按钮点击事件一样辣?哈哈)
//skinObservable.addObserver(new Observer() {
// @Override
// public void update(Observable o, Object arg) {
// }
// });
//4 发布消息(要观察的对象有消息就会通知观察者)
skinObservable.notificationUpdate("更新皮肤辣~~");
//5 退出了记得调用skinObservable.deleteObservers();或skinObservable.deleteObserver(Observer observer);移除观察者
小白:好简单哇,毛毛哥,不过这个单词Observable和Observer我老是忘记搞混
三毛:“这就是你的问题了,怪我咯”
三毛:“下面不使用JDK提供的API,我们自己写”
写个接口,用来通知更新
public interface Observer2 {
void updateSkin(Object object);
}
在写个要观察谁的类
public class SkinObserverB2 implements Observer2{
@Override
public void updateSkin(Object object) {
System.out.println("更新辣,内容是:"+object);
}
}
然后写个观察者的类(其实这个可以写成公共类,然后其他类继承它就好)
public class SkinObservable2 {
private Object mObject;
private List mObservers;
public SkinObservable2(Object object) {
mObject = object;
mObservers = new ArrayList<>();
}
/**
* 添加观察者
*
* @param observer2
*/
public void addObserver(Observer2 observer2) {
if (null != observer2)
mObservers.add(observer2);
}
/**
* 通知观察者更新
*/
public void setUpdateListener() {
for (Observer2 observer2 : mObservers)
observer2.updateSkin(mObject);
}
/**
* 释放内存,清空观察者
*/
public void clearObservers() {
if (null != mObservers)
mObservers.clear();
}
}
使用
//1 创建要观察谁(对象)
SkinObservable2 skinObservable2 = new SkinObservable2("更新皮肤辣~~");
//2 创建观察者
SkinObserverB2 skinObserverB2 = new SkinObserverB2();
//3 将观察者注册到要观察对象的观察者列表中(和按钮点击事件一样辣)
skinObservable2.addObserver(skinObserverB2);
//4 发布消息(要观察的对象有消息就会通知观察者)
skinObservable2.setUpdateListener();
1、可以一对多,也可以多对一;
2、稳定的消息更新传递机制,并抽象了更新接口;
3、对象解耦(架构、模式啥的不都是为了解耦嘛,汗);
4、EventBus、广播、RxJava等都是使用观察者模式,它们使用场景要了解,而JDK已经提供了观察者模式的API,使用也不比它们难